1#! /usr/bin/awk -f 2# $OpenBSD: makemap.awk,v 1.10 2009/01/11 16:54:53 miod Exp $ 3# 4# Copyright (c) 2005, Miodrag Vallat 5# 6# Redistribution and use in source and binary forms, with or without 7# modification, are permitted provided that the following conditions 8# are met: 9# 1. Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# 2. Redistributions in binary form must reproduce the above copyright 12# notice, this list of conditions and the following disclaimer in the 13# documentation and/or other materials provided with the distribution. 14# 15# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18# DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 24# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25# POSSIBILITY OF SUCH DAMAGE. 26# 27# 28# This script attempts to convert, with minimal hacks and losses, the 29# regular PS/2 keyboard (pckbd) layout tables into USB keyboard (ukbd) 30# layout tables. 31# 32 33BEGIN { 34 rcsid = "$OpenBSD: makemap.awk,v 1.10 2009/01/11 16:54:53 miod Exp $" 35 ifdepth = 0 36 ignore = 0 37 declk = 0 38 haskeys = 0 39 kbfr = 0 40 nmaps = 0 41 42 # PS/2 id -> UKBD conversion table, or "sanity lossage 101" 43 for (i = 0; i < 256; i++) 44 conv[i] = -1 45 46 conv[1] = 41 47 conv[2] = 30 48 conv[3] = 31 49 conv[4] = 32 50 conv[5] = 33 51 conv[6] = 34 52 conv[7] = 35 53 conv[8] = 36 54 conv[9] = 37 55 conv[10] = 38 56 conv[11] = 39 57 conv[12] = 45 58 conv[13] = 46 59 conv[14] = 42 60 conv[15] = 43 61 conv[16] = 20 62 conv[17] = 26 63 conv[18] = 8 64 conv[19] = 21 65 conv[20] = 23 66 conv[21] = 28 67 conv[22] = 24 68 conv[23] = 12 69 conv[24] = 18 70 conv[25] = 19 71 conv[26] = 47 72 conv[27] = 48 73 conv[28] = 40 74 conv[29] = 224 75 conv[30] = 4 76 conv[31] = 22 77 conv[32] = 7 78 conv[33] = 9 79 conv[34] = 10 80 conv[35] = 11 81 conv[36] = 13 82 conv[37] = 14 83 conv[38] = 15 84 conv[39] = 51 85 conv[40] = 52 86 conv[41] = 53 87 conv[42] = 225 88 conv[43] = 50 89 conv[44] = 29 90 conv[45] = 27 91 conv[46] = 6 92 conv[47] = 25 93 conv[48] = 5 94 conv[49] = 17 95 conv[50] = 16 96 conv[51] = 54 97 conv[52] = 55 98 conv[53] = 56 99 conv[54] = 229 100 conv[55] = 85 101 conv[56] = 226 102 conv[57] = 44 103 conv[58] = 57 104 conv[59] = 58 105 conv[60] = 59 106 conv[61] = 60 107 conv[62] = 61 108 conv[63] = 62 109 conv[64] = 63 110 conv[65] = 64 111 conv[66] = 65 112 conv[67] = 66 113 conv[68] = 67 114 conv[69] = 83 115 conv[70] = 71 116 conv[71] = 95 117 conv[72] = 96 118 conv[73] = 97 119 conv[74] = 86 120 conv[75] = 92 121 conv[76] = 93 122 conv[77] = 94 123 conv[78] = 87 124 conv[79] = 89 125 conv[80] = 90M 126 conv[81] = 91 127 conv[82] = 98 128 conv[83] = 99 129 conv[86] = 100 130 conv[87] = 68 131 conv[88] = 69 132 conv[112] = 135 133 conv[115] = 136 134 conv[121] = 137 135 conv[123] = 138 136 conv[125] = 139 137 conv[127] = 72 138 conv[156] = 88 139 conv[157] = 228 140 conv[160] = 127 141 conv[170] = 70 142 conv[174] = 129 143 conv[176] = 128 144 conv[181] = 84 145 conv[184] = 230 146 # 198 is #if 0 in the PS/2 map... 147 conv[199] = 74 148 conv[200] = 82 149 conv[201] = 75 150 conv[203] = 80 151 conv[205] = 79 152 conv[207] = 77 153 conv[208] = 81 154 conv[209] = 78 155 conv[210] = 73 156 conv[211] = 99 157 conv[219] = 227 158 conv[220] = 231 159 conv[221] = 101 160} 161NR == 1 { 162 VERSION = $0 163 gsub("\\$", "", VERSION) 164 gsub("\\$", "", rcsid) 165 166 printf("/*\t\$OpenBSD\$\t*/\n\n") 167 printf("/*\n") 168 printf(" * THIS FILE IS AUTOMAGICALLY GENERATED. DO NOT EDIT.\n") 169 printf(" *\n") 170 printf(" * generated by:\n") 171 printf(" *\t%s\n", rcsid) 172 printf(" * generated from:\n") 173 printf(" */\n") 174 print VERSION 175 176 next 177} 178 179# 180# A very limited #if ... #endif parser. We only want to correctly detect 181# ``#if 0'' constructs, so as not to process their contents. This is necessary 182# since our output is out-of-order from our input. 183# 184# Note that this does NOT handle ``#ifdef notyet'' correctly - please only use 185# ``#if 0'' constructs in the input. 186# 187 188/^#if/ { 189 ignores[ifdepth] = ignore 190 if ($2 == "0") 191 ignore = 1 192 else 193 ignore = 0 194 ifdepth++ 195 if (ignore) 196 next 197} 198/^#endif/ { 199 oldignore = ignore 200 ifdepth-- 201 ignore = ignores[ifdepth] 202 ignores[ifdepth] = 0 203 if (oldignore) 204 next 205} 206 207$1 == "#include" { 208 if (ignore) 209 next 210 if ($2 == "<dev/pckbc/wskbdmap_mfii.h>") 211 next 212 printf("#include %s\n", $2) 213 next 214} 215$1 == "#define" || $1 == "#undef" { 216 if (ignore) 217 next 218 print $0 219 next 220} 221 222# Don't bother converting the DEC LK layout. 223/declk\[/ { 224 declk = 1 225 next 226} 227/declk/ { 228 next 229} 230 231/pckbd/ { 232 gsub("pckbd", "ukbd", $0) 233 mapname = $4 234} 235 236/KC/ { 237 if (ignore) 238 next 239 240 if (declk) 241 next 242 243 haskeys = 1 244 245 sidx = substr($1, 4, length($1) - 5) 246 orig = int(sidx) 247 id = conv[orig] 248 249 # 183 is another Print Screen... 250 if (orig == 183) 251 next 252 253 if (id == -1) { 254 printf("/* initially KC(%d),", orig) 255 for (f = 2; f <= NF; f++) { 256 if ($f != "/*" && $f != "*/") 257 printf("\t%s", $f) 258 } 259 printf("\t*/\n") 260 } else { 261 lines[id] = sprintf(" KC(%d),\t", id) 262 # 263 # This makes sure that the non-comment part of the output 264 # ends up with a trailing comma. This is necessary since 265 # the last line of an input block might not have a trailing 266 # comma, but might not be the last line of an output block 267 # due to sorting. 268 # 269 comma = 0 270 for (f = 2; f <= NF; f++) { 271 l = length($f) 272 if ($f == "/*") 273 comma++ 274 if (comma == 0 && substr($f, l) != ",") { 275 lines[id] = sprintf("%s%s,", lines[id], $f) 276 l++ 277 } else { 278 lines[id] = sprintf("%s%s", lines[id], $f) 279 } 280 if (comma == 0 && f != NF) { 281 if (l < 2 * 8) 282 lines[id] = lines[id] "\t" 283 if (l < 8) 284 lines[id] = lines[id] "\t" 285 } 286 if ($f == "*/") 287 comma-- 288 } 289 } 290 291 next 292} 293/};/ { 294 if (ignore) 295 next 296 297 if (declk) { 298 declk = 0 299 next 300 } 301 302 if (haskeys) { 303 # Duplicate 42 (backspace) as 76 and 50 (backslash bar) as 49 304 if (!lines[76]) { 305 lines[76] = lines[42] 306 sub("42", "76", lines[76]) 307 } 308 if (!lines[49]) { 309 lines[49] = lines[50] 310 sub("50", "49", lines[49]) 311 } 312 313 # 314 # Sun USB keyboards extra keys do not appear in the PS/2 315 # maps. We add them here, except for the Compose key (101) 316 # which conflicts with the ``menu'' key. 317 # 318 if (nmaps++ == 0) { 319 # 102 Suspend 320 lines[116] = " KC(116),\tKS_Open," 321 lines[117] = " KC(117),\tKS_Help," 322 lines[118] = " KC(118),\tKS_Props," 323 lines[119] = " KC(119),\tKS_Front," 324 lines[120] = " KC(120),\tKS_Cmd," 325 lines[121] = " KC(121),\tKS_Again," 326 lines[122] = " KC(122),\tKS_Undo," 327 lines[123] = " KC(123),\tKS_Cut," 328 lines[124] = " KC(124),\tKS_Copy," 329 lines[125] = " KC(125),\tKS_Paste," 330 lines[126] = " KC(126),\tKS_Find," 331 } 332 333 for (i = 0; i < 256; i++) 334 if (lines[i]) { 335 print lines[i] 336 lines[i] = "" 337 } 338 339 haskeys = 0 340 341 # 342 # Apple black USB keyboards use a slightly different 343 # layout. We define them here. 344 # 345 if (mapname == "ukbd_keydesc_fr[]") { 346 print $0 347 print "\nstatic const keysym_t ukbd_keydesc_fr_apple[] = {" 348 print " KC(5),\tKS_b,\t\tKS_B,\t\tKS_ssharp," 349 print " KC(8),\tKS_e,\t\tKS_E,\t\tKS_ecircumflex,\tKS_Ecircumflex," 350 print " KC(11),\tKS_h,\t\tKS_H,\t\tKS_Igrave,\tKS_Icircumflex," 351 print " KC(12),\tKS_i,\t\tKS_I,\t\tKS_icircumflex,\tKS_idiaeresis," 352 print " KC(13),\tKS_j,\t\tKS_J,\t\tKS_Idiaeresis,\tKS_Iacute," 353 print " KC(14),\tKS_k,\t\tKS_K,\t\tKS_Egrave,\tKS_Ediaeresis," 354 print " KC(15),\tKS_l,\t\tKS_L,\t\tKS_voidSymbol,\tKS_bar," 355 print " KC(16),\tKS_comma,\tKS_question,\tKS_voidSymbol,\tKS_questiondown," 356 print " KC(17),\tKS_n,\t\tKS_N,\t\tKS_asciitilde," 357 print " KC(20),\tKS_a,\t\tKS_A,\t\tKS_ae,\t\tKS_AE," 358 print " KC(21),\tKS_r,\t\tKS_R,\t\tKS_registered,\tKS_comma," 359 print " KC(22),\tKS_s,\t\tKS_S,\t\tKS_Ograve," 360 print " KC(26),\tKS_z,\t\tKS_Z,\t\tKS_Acircumflex,\tKS_Aring," 361 print " KC(28),\tKS_y,\t\tKS_Y,\t\tKS_Uacute," 362 print " KC(31),\tKS_eacute,\tKS_2,\t\tKS_ediaeresis," 363 print " KC(32),\tKS_quotedbl,\tKS_3," 364 print " KC(33),\tKS_apostrophe,\tKS_4," 365 print " KC(34),\tKS_parenleft,\tKS_5,\t\tKS_braceleft,\tKS_bracketleft," 366 print " KC(35),\tKS_section,\tKS_6," 367 print " KC(36),\tKS_egrave,\tKS_7,\t\tKS_guillemotleft," 368 print "\t\t\t\t\t\tKS_guillemotright," 369 print " KC(37),\tKS_exclam,\tKS_8," 370 print " KC(38),\tKS_ccedilla,\tKS_9,\t\tKS_Ccedilla,\tKS_Aacute," 371 print " KC(37),\tKS_exclam,\tKS_8,\t\tKS_exclamdown,\tKS_Ucircumflex," 372 print " KC(39),\tKS_agrave,\tKS_0,\t\tKS_oslash,\tKS_Ooblique," 373 print " KC(45),\tKS_parenright,\tKS_degree,\tKS_braceright,\tKS_bracketright," 374 print " KC(46),\tKS_minus,\tKS_underscore," 375 print " KC(47),\tKS_dead_circumflex, KS_dead_diaeresis," 376 print "\t\t\t\t\t\tKS_ocircumflex,\tKS_Ocircumflex," 377 print " KC(48),\tKS_dollar,\tKS_asterisk,\tKS_cent,\tKS_yen," 378 print " KC(50),\tKS_grave,\tKS_sterling,\tKS_at,\t\tKS_numbersign," 379 print " KC(51),\tKS_m,\t\tKS_M,\t\tKS_mu,\t\tKS_Oacute," 380 print " KC(52),\tKS_ugrave,\tKS_percent,\tKS_Ugrave," 381 print " KC(53),\tKS_at,\t\tKS_numbersign," 382 print " KC(55),\tKS_colon,\tKS_slash,\tKS_voidSymbol,\tKS_backslash," 383 print " KC(56),\tKS_equal,\tKS_plus," 384 print " KC(103),\tKS_KP_Equal," 385 print " KC(231),\tKS_Mode_switch,\tKS_Multi_key," 386 } else 387 if (mapname == "ukbd_keydesc_pt[]") { 388 print $0 389 print "\nstatic const keysym_t ukbd_keydesc_pt_apple[] = {" 390 print "/* pos\t\tnormal\t\tshifted */" 391 print " KC(46),\tKS_plus,\tKS_asterisk," 392 print " KC(47),\tKS_masculine,\tKS_ordfeminine," 393 print " KC(50),\tKS_backslash,\tKS_bar," 394 print " KC(52),\tKS_dead_tilde,\tKS_dead_circumflex" 395 } 396 } 397} 398/KB_FR/ { 399 print $0 400 kbfr++ 401 # Add .apple variants, but not to the fr.dvorak variants 402 if (kbfr == 1) { 403 print "\tKBD_MAP(KB_FR | KB_APPLE,\tKB_FR,\tukbd_keydesc_fr_apple)," 404 } else if (kbfr == 3) { 405 print "\tKBD_MAP(KB_FR | KB_APPLE | KB_SWAPCTRLCAPS,\tKB_FR | KB_APPLE," 406 print "\t\tukbd_keydesc_swapctrlcaps)," 407 } 408 next 409} 410/KB_PT/ { 411 print $0 412 print "\tKBD_MAP(KB_PT | KB_APPLE,\tKB_PT,\tukbd_keydesc_pt_apple)," 413 next 414} 415{ 416 if (ignore) 417 next 418 if (declk) 419 next 420 print $0 421} 422