1#! /usr/bin/awk -f 2# $OpenBSD: makemap.awk,v 1.15 2020/11/02 19:45:18 tobhe 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.15 2020/11/02 19:45:18 tobhe 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] = 90 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[91] = 104 133 conv[92] = 105 134 conv[93] = 106 135 conv[99] = 107 136 conv[100] = 108 137 conv[101] = 109 138 conv[102] = 110 139 conv[103] = 111 140 conv[104] = 112 141 conv[105] = 113 142 conv[106] = 114 143 conv[107] = 115 144 conv[112] = 136 145 conv[115] = 135 146 conv[121] = 138 147 conv[123] = 139 148 conv[125] = 137 149 conv[127] = 72 150 conv[156] = 88 151 conv[157] = 228 152 conv[160] = 127 153 conv[170] = 70 154 conv[174] = 129 155 conv[176] = 128 156 conv[181] = 84 157 conv[184] = 230 158 # 198 is #if 0 in the PS/2 map... 159 conv[199] = 74 160 conv[200] = 82 161 conv[201] = 75 162 conv[203] = 80 163 conv[205] = 79 164 conv[207] = 77 165 conv[208] = 81 166 conv[209] = 78 167 conv[210] = 73 168 conv[211] = 76 169 conv[219] = 227 170 conv[220] = 231 171 conv[221] = 101 172} 173NR == 1 { 174 VERSION = $0 175 gsub("\\$", "", VERSION) 176 gsub("\\$", "", rcsid) 177 178 printf("/*\t\$OpenBSD\$\t*/\n\n") 179 printf("/*\n") 180 printf(" * THIS FILE IS AUTOMAGICALLY GENERATED. DO NOT EDIT.\n") 181 printf(" *\n") 182 printf(" * generated by:\n") 183 printf(" *\t%s\n", rcsid) 184 printf(" * generated from:\n") 185 printf(" */\n") 186 print VERSION 187 188 next 189} 190 191# 192# A very limited #if ... #endif parser. We only want to correctly detect 193# ``#if 0'' constructs, so as not to process their contents. This is necessary 194# since our output is out-of-order from our input. 195# 196# Note that this does NOT handle ``#ifdef notyet'' correctly - please only use 197# ``#if 0'' constructs in the input. 198# 199 200/^#if/ { 201 ignores[ifdepth] = ignore 202 if ($2 == "0") 203 ignore = 1 204 #else 205 # ignore = 0 206 ifdepth++ 207 if (ignore) 208 next 209} 210/^#endif/ { 211 oldignore = ignore 212 ifdepth-- 213 ignore = ignores[ifdepth] 214 ignores[ifdepth] = 0 215 if (oldignore) 216 next 217} 218 219$1 == "#include" { 220 if (ignore) 221 next 222 if ($2 == "<dev/pckbc/wskbdmap_mfii.h>") 223 next 224 printf("#include %s\n", $2) 225 next 226} 227$1 == "#define" || $1 == "#undef" { 228 if (ignore) 229 next 230 print $0 231 next 232} 233 234# Don't bother converting the DEC LK layout. 235/declk\[/ { 236 declk = 1 237 next 238} 239/declk/ { 240 next 241} 242 243/pckbd/ { 244 gsub("pckbd", "ukbd", $0) 245 mapname = $4 246} 247 248/KC/ { 249 if (ignore) 250 next 251 252 if (declk) 253 next 254 255 haskeys = 1 256 257 sidx = substr($1, 4, length($1) - 5) 258 orig = int(sidx) 259 id = conv[orig] 260 261 # 183 is another Print Screen... 262 if (orig == 183) 263 next 264 265 if (id == -1) { 266 printf("/* initially KC(%d),", orig) 267 for (f = 2; f <= NF; f++) { 268 if ($f != "/*" && $f != "*/") 269 printf("\t%s", $f) 270 } 271 printf("\t*/\n") 272 } else { 273 lines[id] = sprintf(" KC(%d),\t", id) 274 # 275 # This makes sure that the non-comment part of the output 276 # ends up with a trailing comma. This is necessary since 277 # the last line of an input block might not have a trailing 278 # comma, but might not be the last line of an output block 279 # due to sorting. 280 # 281 comma = 0 282 for (f = 2; f <= NF; f++) { 283 l = length($f) 284 if ($f == "/*") 285 comma++ 286 if (comma == 0 && substr($f, l) != ",") { 287 lines[id] = sprintf("%s%s,", lines[id], $f) 288 l++ 289 } else { 290 lines[id] = sprintf("%s%s", lines[id], $f) 291 } 292 if (comma == 0 && f != NF) { 293 if (l < 2 * 8) 294 lines[id] = lines[id] "\t" 295 if (l < 8) 296 lines[id] = lines[id] "\t" 297 } 298 if ($f == "*/") 299 comma-- 300 } 301 } 302 303 next 304} 305/};/ { 306 if (ignore) 307 next 308 309 if (declk) { 310 declk = 0 311 next 312 } 313 314 if (haskeys) { 315 # Duplicate 42 (backspace) as 76 and 50 (backslash bar) as 49 316 if (!lines[76]) { 317 lines[76] = lines[42] 318 sub("42", "76", lines[76]) 319 } 320 if (!lines[49]) { 321 lines[49] = lines[50] 322 sub("50", "49", lines[49]) 323 } 324 325 # 326 # Several USB keyboards have extra keys do not appear in 327 # the traditional PS/2 maps. We add them here, except for 328 # the Sun keyboard Compose key (101) which conflicts with 329 # the ``menu'' key. 330 # 331 if (nmaps++ == 0) { 332 # 102 Suspend 333 lines[116] = " KC(116),\tKS_Open," 334 lines[117] = " KC(117),\tKS_Help," 335 lines[118] = " KC(118),\tKS_Props," 336 lines[119] = " KC(119),\tKS_Front," 337 lines[120] = " KC(120),\tKS_Cmd," 338 lines[121] = " KC(121),\tKS_Again," 339 lines[122] = " KC(122),\tKS_Undo," 340 lines[123] = " KC(123),\tKS_Cut," 341 lines[124] = " KC(124),\tKS_Copy," 342 lines[125] = " KC(125),\tKS_Paste," 343 lines[126] = " KC(126),\tKS_Find," 344 lines[232] = " KC(232),\tKS_Cmd_BrightnessUp," 345 lines[233] = " KC(233),\tKS_Cmd_BrightnessDown," 346 } 347 348 for (i = 0; i < 256; i++) 349 if (lines[i]) { 350 print lines[i] 351 lines[i] = "" 352 } 353 354 haskeys = 0 355 356 # 357 # Apple black USB keyboards use a slightly different 358 # layout. We define them here. 359 # 360 if (mapname == "ukbd_keydesc_fr[]") { 361 print $0 362 print "\nstatic const keysym_t ukbd_keydesc_fr_apple[] = {" 363 print " KC(5),\tKS_b,\t\tKS_B,\t\tKS_ssharp," 364 print " KC(8),\tKS_e,\t\tKS_E,\t\tKS_ecircumflex,\tKS_Ecircumflex," 365 print " KC(11),\tKS_h,\t\tKS_H,\t\tKS_Igrave,\tKS_Icircumflex," 366 print " KC(12),\tKS_i,\t\tKS_I,\t\tKS_icircumflex,\tKS_idiaeresis," 367 print " KC(13),\tKS_j,\t\tKS_J,\t\tKS_Idiaeresis,\tKS_Iacute," 368 print " KC(14),\tKS_k,\t\tKS_K,\t\tKS_Egrave,\tKS_Ediaeresis," 369 print " KC(15),\tKS_l,\t\tKS_L,\t\tKS_voidSymbol,\tKS_bar," 370 print " KC(16),\tKS_comma,\tKS_question,\tKS_voidSymbol,\tKS_questiondown," 371 print " KC(17),\tKS_n,\t\tKS_N,\t\tKS_asciitilde," 372 print " KC(20),\tKS_a,\t\tKS_A,\t\tKS_ae,\t\tKS_AE," 373 print " KC(21),\tKS_r,\t\tKS_R,\t\tKS_registered,\tKS_comma," 374 print " KC(22),\tKS_s,\t\tKS_S,\t\tKS_Ograve," 375 print " KC(26),\tKS_z,\t\tKS_Z,\t\tKS_Acircumflex,\tKS_Aring," 376 print " KC(28),\tKS_y,\t\tKS_Y,\t\tKS_Uacute," 377 print " KC(31),\tKS_eacute,\tKS_2,\t\tKS_ediaeresis," 378 print " KC(32),\tKS_quotedbl,\tKS_3," 379 print " KC(33),\tKS_apostrophe,\tKS_4," 380 print " KC(34),\tKS_parenleft,\tKS_5,\t\tKS_braceleft,\tKS_bracketleft," 381 print " KC(35),\tKS_section,\tKS_6," 382 print " KC(36),\tKS_egrave,\tKS_7,\t\tKS_guillemotleft," 383 print "\t\t\t\t\t\tKS_guillemotright," 384 print " KC(37),\tKS_exclam,\tKS_8," 385 print " KC(38),\tKS_ccedilla,\tKS_9,\t\tKS_Ccedilla,\tKS_Aacute," 386 print " KC(37),\tKS_exclam,\tKS_8,\t\tKS_exclamdown,\tKS_Ucircumflex," 387 print " KC(39),\tKS_agrave,\tKS_0,\t\tKS_oslash,\tKS_Ooblique," 388 print " KC(45),\tKS_parenright,\tKS_degree,\tKS_braceright,\tKS_bracketright," 389 print " KC(46),\tKS_minus,\tKS_underscore," 390 print " KC(47),\tKS_dead_circumflex, KS_dead_diaeresis," 391 print "\t\t\t\t\t\tKS_ocircumflex,\tKS_Ocircumflex," 392 print " KC(48),\tKS_dollar,\tKS_asterisk,\tKS_cent,\tKS_yen," 393 print " KC(50),\tKS_grave,\tKS_sterling,\tKS_at,\t\tKS_numbersign," 394 print " KC(51),\tKS_m,\t\tKS_M,\t\tKS_mu,\t\tKS_Oacute," 395 print " KC(52),\tKS_ugrave,\tKS_percent,\tKS_Ugrave," 396 print " KC(53),\tKS_at,\t\tKS_numbersign," 397 print " KC(55),\tKS_colon,\tKS_slash,\tKS_voidSymbol,\tKS_backslash," 398 print " KC(56),\tKS_equal,\tKS_plus," 399 print " KC(103),\tKS_KP_Equal," 400 print " KC(231),\tKS_Mode_switch,\tKS_Multi_key," 401 } else 402 if (mapname == "ukbd_keydesc_pt[]") { 403 print $0 404 print "\nstatic const keysym_t ukbd_keydesc_pt_apple[] = {" 405 print "/* pos\t\tnormal\t\tshifted */" 406 print " KC(46),\tKS_plus,\tKS_asterisk," 407 print " KC(47),\tKS_masculine,\tKS_ordfeminine," 408 print " KC(50),\tKS_backslash,\tKS_bar," 409 print " KC(52),\tKS_dead_tilde,\tKS_dead_circumflex" 410 } 411 } 412} 413/KB_FR/ { 414 print $0 415 kbfr++ 416 # Add .apple variants, but not to the fr.dvorak variants 417 if (kbfr == 1) { 418 print "\tKBD_MAP(KB_FR | KB_APPLE,\tKB_FR,\tukbd_keydesc_fr_apple)," 419 } else if (kbfr == 3) { 420 print "\tKBD_MAP(KB_FR | KB_APPLE | KB_SWAPCTRLCAPS,\tKB_FR | KB_APPLE," 421 print "\t\tukbd_keydesc_swapctrlcaps)," 422 } 423 next 424} 425/KB_PT/ { 426 print $0 427 print "\tKBD_MAP(KB_PT | KB_APPLE,\tKB_PT,\tukbd_keydesc_pt_apple)," 428 next 429} 430{ 431 if (ignore) 432 next 433 if (declk) 434 next 435 print $0 436} 437