Process a return code of 'write' function
[platform/upstream/kbd.git] / src / loadkeys.y
1 /*
2  * loadkeys.y
3  *
4  * For history, see older versions.
5  */
6
7 %token EOL NUMBER LITERAL CHARSET KEYMAPS KEYCODE EQUALS
8 %token PLAIN SHIFT CONTROL ALT ALTGR SHIFTL SHIFTR CTRLL CTRLR
9 %token COMMA DASH STRING STRLITERAL COMPOSE TO CCHAR ERROR PLUS
10 %token UNUMBER ALT_IS_META STRINGS AS USUAL ON FOR
11
12 %{
13 #include <errno.h>
14 #include <stdio.h>
15 #include <getopt.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <fcntl.h>
19 #include <ctype.h>
20 #include <sys/ioctl.h>
21 #include <linux/kd.h>
22 #include <linux/keyboard.h>
23 #include <unistd.h>             /* readlink */
24 #include "paths.h"
25 #include "getfd.h"
26 #include "findfile.h"
27 #include "modifiers.h"
28 #include "nls.h"
29 #include "version.h"
30
31 #ifndef KT_LETTER
32 #define KT_LETTER KT_LATIN
33 #endif
34
35 #undef NR_KEYS
36 #define NR_KEYS 256
37
38 /* What keymaps are we defining? */
39 char defining[MAX_NR_KEYMAPS];
40 char keymaps_line_seen = 0;
41 int max_keymap = 0;             /* from here on, defining[] is false */
42 int alt_is_meta = 0;
43
44 /* the kernel structures we want to set or print */
45 u_short *key_map[MAX_NR_KEYMAPS];
46 char *func_table[MAX_NR_FUNC];
47 struct kbdiacr accent_table[MAX_DIACR];
48 unsigned int accent_table_size = 0;
49
50 char key_is_constant[NR_KEYS];
51 char *keymap_was_set[MAX_NR_KEYMAPS];
52 char func_buf[4096];            /* should be allocated dynamically */
53 char *fp = func_buf;
54
55 #define U(x) ((x) ^ 0xf000)
56
57 #undef ECHO
58
59 static void addmap(int map, int explicit);
60 static void addkey(int index, int table, int keycode);
61 static void addfunc(struct kbsentry kbs_buf);
62 static void killkey(int index, int table);
63 static void compose(int diacr, int base, int res);
64 static void do_constant(void);
65 static void do_constant_key (int, u_short);
66 static void loadkeys(char *console, int *warned);
67 static void mktable(void);
68 static void bkeymap(void);
69 static void strings_as_usual(void);
70 /* static void keypad_as_usual(char *keyboard); */
71 /* static void function_keys_as_usual(char *keyboard); */
72 /* static void consoles_as_usual(char *keyboard); */
73 static void compose_as_usual(char *charset);
74 static void lkfatal0(const char *, int);
75 extern int set_charset(const char *charset);
76 extern char *xstrdup(char *);
77 int key_buf[MAX_NR_KEYMAPS];
78 int mod;
79 extern int unicode_used;
80 int private_error_ct = 0;
81
82 extern int rvalct;
83 extern struct kbsentry kbs_buf;
84 int yyerror(const char *s);
85 extern void lkfatal(const char *s);
86 extern void lkfatal1(const char *s, const char *s2);
87
88 #include "ksyms.h"
89 int yylex (void);
90 %}
91
92 %%
93 keytable        :
94                 | keytable line
95                 ;
96 line            : EOL
97                 | charsetline
98                 | altismetaline
99                 | usualstringsline
100                 | usualcomposeline
101                 | keymapline
102                 | fullline
103                 | singleline
104                 | strline
105                 | compline
106                 ;
107 charsetline     : CHARSET STRLITERAL EOL
108                         {
109                             set_charset((char *) kbs_buf.kb_string);
110                         }
111                 ;
112 altismetaline   : ALT_IS_META EOL
113                         {
114                             alt_is_meta = 1;
115                         }
116                 ;
117 usualstringsline: STRINGS AS USUAL EOL
118                         {
119                             strings_as_usual();
120                         }
121                 ;
122 usualcomposeline: COMPOSE AS USUAL FOR STRLITERAL EOL
123                         {
124                             compose_as_usual((char *) kbs_buf.kb_string);
125                         }
126                   | COMPOSE AS USUAL EOL
127                         {
128                             compose_as_usual(0);
129                         }
130                 ;
131 keymapline      : KEYMAPS range EOL
132                         {
133                             keymaps_line_seen = 1;
134                         }
135                 ;
136 range           : range COMMA range0
137                 | range0
138                 ;
139 range0          : NUMBER DASH NUMBER
140                         {
141                             int i;
142                             for (i = $1; i<= $3; i++)
143                               addmap(i,1);
144                         }
145                 | NUMBER
146                         {
147                             addmap($1,1);
148                         }
149                 ;
150 strline         : STRING LITERAL EQUALS STRLITERAL EOL
151                         {
152                             if (KTYP($2) != KT_FN)
153                                 lkfatal1(_("'%s' is not a function key symbol"),
154                                         syms[KTYP($2)].table[KVAL($2)]);
155                             kbs_buf.kb_func = KVAL($2);
156                             addfunc(kbs_buf);
157                         }
158                 ;
159 compline        : COMPOSE CCHAR CCHAR TO CCHAR EOL
160                         {
161                             compose($2, $3, $5);
162                         }
163                  | COMPOSE CCHAR CCHAR TO rvalue EOL
164                         {
165                             compose($2, $3, $5);
166                         }
167                 ;
168 singleline      :       { mod = 0; }
169                   modifiers KEYCODE NUMBER EQUALS rvalue EOL
170                         {
171                             addkey($4, mod, $6);
172                         }
173                 | PLAIN KEYCODE NUMBER EQUALS rvalue EOL
174                         {
175                             addkey($3, 0, $5);
176                         }
177                 ;
178 modifiers       : modifiers modifier
179                 | modifier
180                 ;
181 modifier        : SHIFT         { mod |= M_SHIFT;       }
182                 | CONTROL       { mod |= M_CTRL;        }
183                 | ALT           { mod |= M_ALT;         }
184                 | ALTGR         { mod |= M_ALTGR;       }
185                 | SHIFTL        { mod |= M_SHIFTL;      }
186                 | SHIFTR        { mod |= M_SHIFTR;      }
187                 | CTRLL         { mod |= M_CTRLL;       }
188                 | CTRLR         { mod |= M_CTRLR;       }
189                 ;
190 fullline        : KEYCODE NUMBER EQUALS rvalue0 EOL
191         {
192             int i, j;
193
194             if (rvalct == 1) {
195               /* Some files do not have a keymaps line, and
196                  we have to wait until all input has been read
197                  before we know which maps to fill. */
198               key_is_constant[$2] = 1;
199
200               /* On the other hand, we now have include files,
201                  and it should be possible to override lines
202                  from an include file. So, kill old defs. */
203               for (j = 0; j < max_keymap; j++)
204                 if (defining[j])
205                   killkey($2, j);
206             }
207             if (keymaps_line_seen) {
208                 i = 0;
209                 for (j = 0; j < max_keymap; j++)
210                   if (defining[j]) {
211                       if (rvalct != 1 || i == 0)
212                         addkey($2, j, (i < rvalct) ? key_buf[i] : K_HOLE);
213                       i++;
214                   }
215                 if (i < rvalct)
216                     lkfatal0(_("too many (%d) entries on one line"), rvalct);
217             } else
218               for (i = 0; i < rvalct; i++)
219                 addkey($2, i, key_buf[i]);
220         }
221                 ;
222
223 rvalue0         : 
224                 | rvalue1 rvalue0
225                 ;
226 rvalue1         : rvalue
227                         {
228                             if (rvalct >= MAX_NR_KEYMAPS)
229                                 lkfatal(_("too many keydefinitions on one line"));
230                             key_buf[rvalct++] = $1;
231                         }
232                 ;
233 rvalue          : NUMBER
234                         {$$=$1;}
235                 | UNUMBER
236                         {$$=($1 ^ 0xf000); unicode_used=1;}
237                 | PLUS NUMBER
238                         {$$=add_capslock($2);}
239                 | LITERAL
240                         {$$=$1;}
241                 | PLUS LITERAL
242                         {$$=add_capslock($2);}
243                 ;
244 %%                      
245
246 #include "analyze.c"
247
248 void
249 usage(void) {
250         fprintf(stderr, _("loadkeys version %s\n"
251 "\n"
252 "Usage: loadkeys [option...] [mapfile...]\n"
253 "\n"
254 "valid options are:\n"
255 "\n"
256 "       -b --bkeymap      output a binary keymap to stdout\n"
257 "       -c --clearcompose clear kernel compose table\n"
258 "       -C <cons1,cons2,...>\n"
259 "       --console=<...>   Indicate console device(s) to be used.\n"
260 "       -d --default      load \"" DEFMAP "\"\n"
261 "       -h --help         display this help text\n"
262 "       -m --mktable      output a \"defkeymap.c\" to stdout\n"
263 "       -s --clearstrings clear kernel string table\n"
264 "       -u --unicode      implicit conversion to Unicode\n"
265 "       -v --verbose      report the changes\n"), PACKAGE_VERSION);
266         exit(1);
267 }
268
269 char **args;
270 int optb = 0;
271 int optd = 0;
272 int optm = 0;
273 int opts = 0;
274 int verbose = 0;
275 int quiet = 0;
276 int nocompose = 0;
277
278 int
279 main(int argc, char *argv[]) {
280         const char *short_opts = "bcC:dhmsuqvV";
281         const struct option long_opts[] = {
282                 { "bkeymap",    no_argument, NULL, 'b' },
283                 { "clearcompose", no_argument, NULL, 'c' },
284                 { "console",    1, NULL, 'C' },
285                 { "default",    no_argument, NULL, 'd' },
286                 { "help",       no_argument, NULL, 'h' },
287                 { "mktable",    no_argument, NULL, 'm' },
288                 { "clearstrings", no_argument, NULL, 's' },
289                 { "unicode",    no_argument, NULL, 'u' },
290                 { "quiet",      no_argument, NULL, 'q' },
291                 { "verbose",    no_argument, NULL, 'v' },
292                 { "version",    no_argument, NULL, 'V' },
293                 { NULL, 0, NULL, 0 }
294         };
295         int c;
296         char *console = NULL;
297         int warned = 0;
298
299         set_progname(argv[0]);
300
301         while ((c = getopt_long(argc, argv,
302                 short_opts, long_opts, NULL)) != -1) {
303                 switch (c) {
304                         case 'b':
305                                 optb = 1;
306                                 break;
307                         case 'c':
308                                 nocompose = 1;
309                                 break;
310                         case 'C':
311                                 console = optarg;
312                                 break;
313                         case 'd':
314                                 optd = 1;
315                                 break;
316                         case 'm':
317                                 optm = 1;
318                                 break;
319                         case 's':
320                                 opts = 1;
321                                 break;
322                         case 'u':
323                                 set_charset("unicode");
324                                 break;
325                         case 'q':
326                                 quiet = 1;
327                                 break;
328                         case 'v':
329                                 verbose++;
330                                 break;
331                         case 'V':
332                                 print_version_and_exit();
333                         case 'h':
334                         case '?':
335                                 usage();
336                 }
337         }
338
339         args = argv + optind - 1;
340         unicode_used = 0;
341         yywrap();       /* set up the first input file, if any */
342         if (yyparse() || private_error_ct) {
343                 fprintf(stderr, _("syntax error in map file\n"));
344                 if(!optm)
345                   fprintf(stderr, _("key bindings not changed\n"));
346                 exit(1);
347         }
348         do_constant();
349         if(optb) {
350                 bkeymap();
351         } else if(optm) {
352                 mktable();
353         } else if (console)
354           {
355             char *buf = strdup(console);        /* make writable */
356             char *e, *s = buf;
357             while (*s)
358               {
359                 while (      *s == ' ' || *s == '\t' || *s == ',') s++;
360                 e = s;
361                 while (*e && *e != ' ' && *e != '\t' && *e != ',') e++;
362                 char c = *e;
363                 *e = '\0';
364                 if (verbose) printf("%s\n", s);
365                 loadkeys(s, &warned);
366                 *e = c;
367                 s = e;
368               }
369             free(buf);
370           }
371         else
372           loadkeys(NULL, &warned);
373         exit(0);
374 }
375
376 extern char pathname[];
377 char *filename;
378 int line_nr = 1;
379
380 int
381 yyerror(const char *s) {
382         fprintf(stderr, "%s:%d: %s\n", filename, line_nr, s);
383         private_error_ct++;
384         return(0);
385 }
386
387 /* fatal errors - change to varargs next time */
388 void
389 lkfatal(const char *s) {
390         fprintf(stderr, "%s: %s:%d: %s\n", progname, filename, line_nr, s);
391         exit(1);
392 }
393
394 void
395 lkfatal0(const char *s, int d) {
396         fprintf(stderr, "%s: %s:%d: ", progname, filename, line_nr);
397         fprintf(stderr, s, d);
398         fprintf(stderr, "\n");
399         exit(1);
400 }
401
402 void
403 lkfatal1(const char *s, const char *s2) {
404         fprintf(stderr, "%s: %s:%d: ", progname, filename, line_nr);
405         fprintf(stderr, s, s2);
406         fprintf(stderr, "\n");
407         exit(1);
408 }
409
410 /* Include file handling - unfortunately flex-specific. */
411 #define MAX_INCLUDE_DEPTH 20
412 struct infile {
413         int linenr;
414         char *filename;
415         YY_BUFFER_STATE bs;
416 } infile_stack[MAX_INCLUDE_DEPTH];
417 int infile_stack_ptr = 0;
418
419 void
420 lk_push(void) {
421         if (infile_stack_ptr >= MAX_INCLUDE_DEPTH)
422                 lkfatal(_("includes nested too deeply"));
423
424         /* preserve current state */
425         infile_stack[infile_stack_ptr].filename = filename;
426         infile_stack[infile_stack_ptr].linenr = line_nr;
427         infile_stack[infile_stack_ptr++].bs =
428                 YY_CURRENT_BUFFER;
429 }
430
431 int
432 lk_pop(void) {
433         if (--infile_stack_ptr >= 0) {
434                 filename = infile_stack[infile_stack_ptr].filename;
435                 line_nr = infile_stack[infile_stack_ptr].linenr;
436                 yy_delete_buffer(YY_CURRENT_BUFFER);
437                 yy_switch_to_buffer(infile_stack[infile_stack_ptr].bs);
438                 return 0;
439         }
440         return 1;
441 }
442
443 /*
444  * Where shall we look for an include file?
445  * Current strategy (undocumented, may change):
446  *
447  * 1. Look for a user-specified LOADKEYS_INCLUDE_PATH
448  * 2. Try . and ../include and ../../include
449  * 3. Try D and D/../include and D/../../include
450  *    where D is the directory from where we are loading the current file.
451  * 4. Try KD/include and KD/#/include where KD = DATADIR/KEYMAPDIR.
452  *
453  * Expected layout:
454  * KD has subdirectories amiga, atari, i386, mac, sun, include
455  * KD/include contains architecture-independent stuff
456  * like strings and iso-8859-x compose tables.
457  * KD/i386 has subdirectories qwerty, ... and include;
458  * this latter include dir contains stuff with keycode=...
459  *
460  * (Of course, if the present setup turns out to be reasonable,
461  * then later also the other architectures will grow and get
462  * subdirectories, and the hard-coded i386 below will go again.)
463  *
464  * People that dislike a dozen lookups for loadkeys
465  * can easily do "loadkeys file_with_includes; dumpkeys > my_keymap"
466  * and afterwards use only "loadkeys /fullpath/mykeymap", where no
467  * lookups are required.
468  */
469 char *include_dirpath0[] = { "", 0 };
470 char *include_dirpath1[] = { "", "../include/", "../../include/", 0 };
471 char *include_dirpath2[] = { 0, 0, 0, 0 };
472 char *include_dirpath3[] = { DATADIR "/" KEYMAPDIR "/include/",
473                              DATADIR "/" KEYMAPDIR "/i386/include/",
474                              DATADIR "/" KEYMAPDIR "/mac/include/", 0 };
475 char *include_suffixes[] = { "", ".inc", 0 };
476
477 FILE *find_incl_file_near_fn(char *s, char *fn) {
478         FILE *f = NULL;
479         char *t, *te, *t1, *t2;
480         int len;
481
482         if (!fn)
483                 return NULL;
484
485         t = xstrdup(fn);
486         te = rindex(t, '/');
487         if (te) {
488                 te[1] = 0;
489                 include_dirpath2[0] = t;
490                 len = strlen(t);
491                 include_dirpath2[1] = t1 = xmalloc(len + 12);
492                 include_dirpath2[2] = t2 = xmalloc(len + 15);
493                 strcpy(t1, t);
494                 strcat(t1, "../include/");
495                 strcpy(t2, t);
496                 strcat(t2, "../../include/");
497                 f = findfile(s, include_dirpath2, include_suffixes);
498                 if (f)
499                         return f;
500         }
501         return f;
502 }
503
504 FILE *find_standard_incl_file(char *s) {
505         FILE *f;
506
507         f = findfile(s, include_dirpath1, include_suffixes);
508         if (!f)
509                 f = find_incl_file_near_fn(s, filename);
510
511         /* If filename is a symlink, also look near its target. */
512         if (!f) {
513                 char buf[1024], path[1024], *p;
514                 int n;
515
516                 n = readlink(filename, buf, sizeof(buf));
517                 if (n > 0 && n < sizeof(buf)) {
518                      buf[n] = 0;
519                      if (buf[0] == '/')
520                           f = find_incl_file_near_fn(s, buf);
521                      else if (strlen(filename) + n < sizeof(path)) {
522                           strcpy(path, filename);
523                           path[sizeof(path)-1] = 0;
524                           p = rindex(path, '/');
525                           if (p)
526                                p[1] = 0;
527                           strcat(path, buf);
528                           f = find_incl_file_near_fn(s, path);
529                      }
530                 }
531         }
532
533         if (!f)
534              f = findfile(s, include_dirpath3, include_suffixes);
535         return f;
536 }
537
538 FILE *find_incl_file(char *s) {
539         FILE *f;
540         char *ev;
541         if (!s || !*s)
542                 return NULL;
543         if (*s == '/')          /* no path required */
544                 return (findfile(s, include_dirpath0, include_suffixes));
545
546         if((ev = getenv("LOADKEYS_INCLUDE_PATH")) != NULL) {
547                 /* try user-specified path */
548                 char *user_dir[2] = { 0, 0 };
549                 while(ev) {
550                         char *t = index(ev, ':');
551                         char sv = 0;
552                         if (t) {
553                                 sv = *t;
554                                 *t = 0;
555                         }
556                         user_dir[0] = ev;
557                         if (*ev)
558                                 f = findfile(s, user_dir, include_suffixes);
559                         else    /* empty string denotes system path */
560                                 f = find_standard_incl_file(s);
561                         if (f)
562                                 return f;
563                         if (t)
564                                 *t++ = sv;
565                         ev = t;
566                 }
567                 return NULL;
568         }
569         return find_standard_incl_file(s);
570 }
571
572 void
573 open_include(char *s) {
574
575         if (verbose)
576                 /* start reading include file */
577                 fprintf(stdout, _("switching to %s\n"), s);
578
579         lk_push();
580
581         yyin = find_incl_file(s);
582         if (!yyin)
583                 lkfatal1(_("cannot open include file %s"), s);
584         filename = xstrdup(pathname);
585         line_nr = 1;
586         yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
587 }
588
589 /* String file handling - flex-specific. */
590 int in_string = 0;
591
592 void
593 lk_scan_string(char *s) {
594         lk_push();
595         in_string = 1;
596         yy_scan_string(s);
597 }
598
599 void
600 lk_end_string(void) {
601         lk_pop();
602         in_string = 0;
603 }
604
605 char *dirpath[] = { "", DATADIR "/" KEYMAPDIR "/**", KERNDIR "/", 0 };
606 char *suffixes[] = { "", ".kmap", ".map", 0 };
607 extern FILE *findfile(char *fnam, char **dirpath, char **suffixes);
608
609 #undef yywrap
610 int
611 yywrap(void) {
612         FILE *f;
613         static int first_file = 1; /* ugly kludge flag */
614
615         if (in_string) {
616                 lk_end_string();
617                 return 0;
618         }
619
620         if (infile_stack_ptr > 0) {
621                 lk_pop();
622                 return 0;
623         }
624
625         line_nr = 1;
626         if (optd) {
627                 /* first read default map - search starts in . */
628                 optd = 0;
629                 if((f = findfile(DEFMAP, dirpath, suffixes)) == NULL) {
630                     fprintf(stderr, _("Cannot find %s\n"), DEFMAP);
631                     exit(1);
632                 }
633                 goto gotf;
634         }
635         if (*args)
636                 args++;
637         if (!*args)
638                 return 1;
639         if (!strcmp(*args, "-")) {
640                 f = stdin;
641                 strcpy(pathname, "<stdin>");
642         } else if ((f = findfile(*args, dirpath, suffixes)) == NULL) {
643                 fprintf(stderr, _("cannot open file %s\n"), *args);
644                 exit(1);
645         }
646         /*
647                 Can't use yyrestart if this is called before entering yyparse()
648                 I think assigning directly to yyin isn't necessarily safe in
649                 other situations, hence the flag.
650         */
651       gotf:
652         filename = xstrdup(pathname);
653         if (!quiet && !optm)
654                 fprintf(stdout, _("Loading %s\n"), pathname);
655         if (first_file) {
656                 yyin = f;
657                 first_file = 0;
658         } else
659                 yyrestart(f);
660         return 0;
661 }
662
663 static void
664 addmap(int i, int explicit) {
665         if (i < 0 || i >= MAX_NR_KEYMAPS)
666             lkfatal0(_("addmap called with bad index %d"), i);
667
668         if (!defining[i]) {
669             if (keymaps_line_seen && !explicit)
670                 lkfatal0(_("adding map %d violates explicit keymaps line"), i);
671
672             defining[i] = 1;
673             if (max_keymap <= i)
674               max_keymap = i+1;
675         }
676 }
677
678 /* unset a key */
679 static void
680 killkey(int index, int table) {
681         /* roughly: addkey(index, table, K_HOLE); */
682
683         if (index < 0 || index >= NR_KEYS)
684                 lkfatal0(_("killkey called with bad index %d"), index);
685         if (table < 0 || table >= MAX_NR_KEYMAPS)
686                 lkfatal0(_("killkey called with bad table %d"), table);
687         if (key_map[table])
688                 (key_map[table])[index] = K_HOLE;
689         if (keymap_was_set[table])
690                 (keymap_was_set[table])[index] = 0;
691 }
692
693 static void
694 addkey(int index, int table, int keycode) {
695         int i;
696
697         if (keycode == CODE_FOR_UNKNOWN_KSYM)
698           /* is safer not to be silent in this case, 
699            * it can be caused by coding errors as well. */
700                 lkfatal0(_("addkey called with bad keycode %d"), keycode);
701         if (index < 0 || index >= NR_KEYS)
702                 lkfatal0(_("addkey called with bad index %d"), index);
703         if (table < 0 || table >= MAX_NR_KEYMAPS)
704                 lkfatal0(_("addkey called with bad table %d"), table);
705
706         if (!defining[table])
707                 addmap(table, 0);
708         if (!key_map[table]) {
709                 key_map[table] = (u_short *)xmalloc(NR_KEYS * sizeof(u_short));
710                 for (i = 0; i < NR_KEYS; i++)
711                   (key_map[table])[i] = K_HOLE;
712         }
713         if (!keymap_was_set[table]) {
714                 keymap_was_set[table] = (char *) xmalloc(NR_KEYS);
715                 for (i = 0; i < NR_KEYS; i++)
716                   (keymap_was_set[table])[i] = 0;
717         }
718
719         if (alt_is_meta && keycode == K_HOLE && (keymap_was_set[table])[index])
720                 return;
721
722         (key_map[table])[index] = keycode;
723         (keymap_was_set[table])[index] = 1;
724
725         if (alt_is_meta) {
726              int alttable = table | M_ALT;
727              int type = KTYP(keycode);
728              int val = KVAL(keycode);
729              if (alttable != table && defining[alttable] &&
730                  (!keymap_was_set[alttable] ||
731                   !(keymap_was_set[alttable])[index]) &&
732                  (type == KT_LATIN || type == KT_LETTER) && val < 128)
733                   addkey(index, alttable, K(KT_META, val));
734         }
735 }
736
737 static void
738 addfunc(struct kbsentry kbs) {
739         int sh, i, x;
740         char *p, *q, *r;
741
742         x = kbs.kb_func;
743
744         if (x >= MAX_NR_FUNC) {
745                 fprintf(stderr, _("%s: addfunc called with bad func %d\n"),
746                         progname, kbs.kb_func);
747                 exit(1);
748         }
749
750         q = func_table[x];
751         if (q) {                        /* throw out old previous def */
752                 sh = strlen(q) + 1;
753                 p = q + sh;
754                 while (p < fp)
755                         *q++ = *p++;
756                 fp -= sh;
757
758                 for (i = x + 1; i < MAX_NR_FUNC; i++)
759                      if (func_table[i])
760                           func_table[i] -= sh;
761         }
762
763         p = func_buf;                        /* find place for new def */
764         for (i = 0; i < x; i++)
765                 if (func_table[i]) {
766                         p = func_table[i];
767                         while(*p++);
768                 }
769         func_table[x] = p;
770         sh = strlen((char *) kbs.kb_string) + 1;
771         if (fp + sh > func_buf + sizeof(func_buf)) {
772                 fprintf(stderr,
773                         _("%s: addfunc: func_buf overflow\n"), progname);
774                 exit(1);
775         }
776         q = fp;
777         fp += sh;
778         r = fp;
779         while (q > p)
780                 *--r = *--q;
781         strcpy(p, (char *) kbs.kb_string);
782         for (i = x + 1; i < MAX_NR_FUNC; i++)
783                 if (func_table[i])
784                         func_table[i] += sh;
785 }
786
787 static void
788 compose(int diacr, int base, int res) {
789         struct kbdiacr *p;
790         if (accent_table_size == MAX_DIACR) {
791                 fprintf(stderr, _("compose table overflow\n"));
792                 exit(1);
793         }
794         p = &accent_table[accent_table_size++];
795         p->diacr = diacr;
796         p->base = base;
797         p->result = res;
798 }
799
800 static int
801 defkeys(int fd, char *cons, int *warned) {
802         struct kbentry ke;
803         int ct = 0;
804         int i,j,fail;
805         int oldm;
806
807         if (unicode_used) {
808              /* Switch keyboard mode for a moment -
809                 do not complain about errors.
810                 Do not attempt a reset if the change failed. */
811              if (ioctl(fd, KDGKBMODE, &oldm)
812                 || (oldm != K_UNICODE && ioctl(fd, KDSKBMODE, K_UNICODE)))
813                   oldm = K_UNICODE;
814         }
815
816         for(i=0; i<MAX_NR_KEYMAPS; i++) {
817             if (key_map[i]) {
818                 for(j=0; j<NR_KEYS; j++) {
819                     if ((keymap_was_set[i])[j]) {
820                         ke.kb_index = j;
821                         ke.kb_table = i;
822                         ke.kb_value = (key_map[i])[j];
823
824                         fail = ioctl(fd, KDSKBENT, (unsigned long)&ke);
825                         if (fail) {
826                             if (errno == EPERM) {
827                                 fprintf(stderr,
828                                         _("Keymap %d: Permission denied\n"), i);
829                                 j = NR_KEYS;
830                                 continue;
831                             }
832                             perror("KDSKBENT");
833                         } else
834                           ct++;
835                         if(verbose)
836                           printf("keycode %d, table %d = %d%s\n", j, i,
837                                  (key_map[i])[j], fail ? _("    FAILED") : "");
838                         else if (fail)
839                           fprintf(stderr,
840                                   _("failed to bind key %d to value %d\n"),
841                                   j, (key_map[i])[j]);
842                     }
843                 }
844             } else if (keymaps_line_seen && !defining[i]) {
845                 /* deallocate keymap */
846                 ke.kb_index = 0;
847                 ke.kb_table = i;
848                 ke.kb_value = K_NOSUCHMAP;
849
850                 if (verbose > 1)
851                   printf(_("deallocate keymap %d\n"), i);
852
853                 if(ioctl(fd, KDSKBENT, (unsigned long)&ke)) {
854                     if (errno != EINVAL) {
855                         perror("KDSKBENT");
856                         fprintf(stderr,
857                                 _("%s: could not deallocate keymap %d\n"),
858                                 progname, i);
859                         exit(1);
860                     }
861                     /* probably an old kernel */
862                     /* clear keymap by hand */
863                     for (j = 0; j < NR_KEYS; j++) {
864                         ke.kb_index = j;
865                         ke.kb_table = i;
866                         ke.kb_value = K_HOLE;
867                         if(ioctl(fd, KDSKBENT, (unsigned long)&ke)) {
868                             if (errno == EINVAL && i >= 16)
869                               break; /* old kernel */
870                             perror("KDSKBENT");
871                             fprintf(stderr,
872                                     _("%s: cannot deallocate or clear keymap\n"),
873                                     progname);
874                             exit(1);
875                         }
876                     }
877                 }
878             }
879         }
880
881         if(unicode_used && oldm != K_UNICODE) {
882              if (ioctl(fd, KDSKBMODE, oldm)) {
883                   fprintf(stderr, _("%s: failed to restore keyboard mode\n"),
884                           progname);
885              }
886
887              if (!warned++)
888                {
889                      int kd_mode = -1;
890                      if (ioctl(fd, KDGETMODE, &kd_mode) || (kd_mode != KD_GRAPHICS))
891                        {
892                          /*
893                           * It is okay for the graphics console to have a non-unicode mode.
894                           * only talk about other consoles
895                           */
896                          fprintf(stderr, _("%s: warning: this map uses Unicode symbols, %s mode=%d\n"
897                                      "    (perhaps you want to do `kbd_mode -u'?)\n"),
898                              progname, cons ? cons : "NULL", kd_mode);
899                        }
900                }
901         }
902         return ct;
903 }
904
905 static char *
906 ostr(char *s) {
907         int lth = strlen(s);
908         char *ns0 = xmalloc(4*lth + 1);
909         char *ns = ns0;
910
911         while(*s) {
912           switch(*s) {
913           case '\n':
914             *ns++ = '\\';
915             *ns++ = 'n';
916             break;
917           case '\033':
918             *ns++ = '\\';
919             *ns++ = '0';
920             *ns++ = '3';
921             *ns++ = '3';
922             break;
923           default:
924             *ns++ = *s;
925           }
926           s++;
927         }
928         *ns = 0;
929         return ns0;
930 }
931
932 static int
933 deffuncs(int fd){
934         int i, ct = 0;
935         char *p;
936
937         for (i = 0; i < MAX_NR_FUNC; i++) {
938             kbs_buf.kb_func = i;
939             if ((p = func_table[i])) {
940                 strcpy((char *) kbs_buf.kb_string, p);
941                 if (ioctl(fd, KDSKBSENT, (unsigned long)&kbs_buf))
942                   fprintf(stderr, _("failed to bind string '%s' to function %s\n"),
943                           ostr(kbs_buf.kb_string), syms[KT_FN].table[kbs_buf.kb_func]);
944                 else
945                   ct++;
946             } else if (opts) {
947                 kbs_buf.kb_string[0] = 0;
948                 if (ioctl(fd, KDSKBSENT, (unsigned long)&kbs_buf))
949                   fprintf(stderr, _("failed to clear string %s\n"),
950                           syms[KT_FN].table[kbs_buf.kb_func]);
951                 else
952                   ct++;
953             }
954           }
955         return ct;
956 }
957
958 static int
959 defdiacs(int fd){
960         struct kbdiacrs kd;
961         int i;
962
963         kd.kb_cnt = accent_table_size;
964         if (kd.kb_cnt > MAX_DIACR) {
965             kd.kb_cnt = MAX_DIACR;
966             fprintf(stderr, _("too many compose definitions\n"));
967         }
968         for (i = 0; i < kd.kb_cnt; i++)
969             kd.kbdiacr[i] = accent_table[i];
970
971         if(ioctl(fd, KDSKBDIACR, (unsigned long) &kd)) {
972             perror("KDSKBDIACR");
973             exit(1);
974         }
975         return kd.kb_cnt;
976 }
977
978 void
979 do_constant_key (int i, u_short key) {
980         int typ, val, j;
981
982         typ = KTYP(key);
983         val = KVAL(key);
984         if ((typ == KT_LATIN || typ == KT_LETTER) &&
985             ((val >= 'a' && val <= 'z') ||
986              (val >= 'A' && val <= 'Z'))) {
987                 u_short defs[16];
988                 defs[0] = K(KT_LETTER, val);
989                 defs[1] = K(KT_LETTER, val ^ 32);
990                 defs[2] = defs[0];
991                 defs[3] = defs[1];
992                 for(j=4; j<8; j++)
993                         defs[j] = K(KT_LATIN, val & ~96);
994                 for(j=8; j<16; j++)
995                         defs[j] = K(KT_META, KVAL(defs[j-8]));
996                 for(j=0; j<max_keymap; j++) {
997                         if (!defining[j])
998                                 continue;
999                         if (j > 0 &&
1000                             keymap_was_set[j] && (keymap_was_set[j])[i])
1001                                 continue;
1002                         addkey(i, j, defs[j%16]);
1003                 }
1004         } else {
1005                 /* do this also for keys like Escape,
1006                    as promised in the man page */
1007                 for (j=1; j<max_keymap; j++)
1008                         if(defining[j] &&
1009                             (!(keymap_was_set[j]) || !(keymap_was_set[j])[i]))
1010                                 addkey(i, j, key);
1011         }
1012 }
1013
1014 static void
1015 do_constant (void) {
1016         int i, r0 = 0;
1017
1018         if (keymaps_line_seen)
1019                 while (r0 < max_keymap && !defining[r0])
1020                         r0++;
1021
1022         for (i=0; i<NR_KEYS; i++) {
1023                 if (key_is_constant[i]) {
1024                         u_short key;
1025                         if (!key_map[r0])
1026                                 lkfatal(_("impossible error in do_constant"));
1027                         key = (key_map[r0])[i];
1028                         do_constant_key (i, key);
1029                 }
1030         }
1031 }
1032
1033 static void
1034 loadkeys (char *console, int *warned) {
1035         int fd;
1036         int keyct, funcct, diacct = 0;
1037
1038         fd = getfd(console);
1039         keyct = defkeys(fd, console, warned);
1040         funcct = deffuncs(fd);
1041         if (verbose) {
1042                 printf(_("\nChanged %d %s and %d %s.\n"),
1043                        keyct, (keyct == 1) ? _("key") : _("keys"),
1044                        funcct, (funcct == 1) ? _("string") : _("strings"));
1045         }
1046         if (accent_table_size > 0 || nocompose) {
1047           diacct = defdiacs(fd);
1048           if (verbose) {
1049                         printf(_("Loaded %d compose %s.\n"), diacct,
1050                                (diacct == 1) ? _("definition") : _("definitions"));
1051           }
1052         }
1053         else
1054           if (verbose)
1055             printf(_("(No change in compose definitions.)\n"));
1056 }
1057
1058 static void strings_as_usual(void) {
1059         /*
1060          * 26 strings, mostly inspired by the VT100 family
1061          */
1062         char *stringvalues[30] = {
1063                 /* F1 .. F20 */
1064                 "\033[[A", "\033[[B", "\033[[C", "\033[[D", "\033[[E",
1065                 "\033[17~", "\033[18~", "\033[19~", "\033[20~", "\033[21~",
1066                 "\033[23~", "\033[24~", "\033[25~", "\033[26~",
1067                 "\033[28~", "\033[29~",
1068                 "\033[31~", "\033[32~", "\033[33~", "\033[34~",
1069                 /* Find,    Insert,    Remove,    Select,    Prior */
1070                 "\033[1~", "\033[2~", "\033[3~", "\033[4~", "\033[5~",
1071                 /* Next,    Macro,  Help, Do,  Pause */
1072                 "\033[6~",    0,      0,   0,    0
1073         };
1074         int i;
1075         for (i=0; i<30; i++) if(stringvalues[i]) {
1076                 struct kbsentry ke;
1077                 ke.kb_func = i;
1078                 strncpy((char *) ke.kb_string, stringvalues[i], sizeof(ke.kb_string));
1079                 ke.kb_string[sizeof(ke.kb_string)-1] = 0;
1080                 addfunc(ke);
1081         }
1082 }
1083
1084 static void
1085 compose_as_usual(char *charset) {
1086         if (charset && strcmp(charset, "iso-8859-1")) {
1087                 fprintf(stderr, _("loadkeys: don't know how to compose for %s\n"),
1088                         charset);
1089                 exit(1);
1090         } else {
1091                 struct ccc {
1092                         char c1, c2, c3;
1093                 } def_latin1_composes[68] = {
1094                         { '`', 'A', 0300 }, { '`', 'a', 0340 },
1095                         { '\'', 'A', 0301 }, { '\'', 'a', 0341 },
1096                         { '^', 'A', 0302 }, { '^', 'a', 0342 },
1097                         { '~', 'A', 0303 }, { '~', 'a', 0343 },
1098                         { '"', 'A', 0304 }, { '"', 'a', 0344 },
1099                         { 'O', 'A', 0305 }, { 'o', 'a', 0345 },
1100                         { '0', 'A', 0305 }, { '0', 'a', 0345 },
1101                         { 'A', 'A', 0305 }, { 'a', 'a', 0345 },
1102                         { 'A', 'E', 0306 }, { 'a', 'e', 0346 },
1103                         { ',', 'C', 0307 }, { ',', 'c', 0347 },
1104                         { '`', 'E', 0310 }, { '`', 'e', 0350 },
1105                         { '\'', 'E', 0311 }, { '\'', 'e', 0351 },
1106                         { '^', 'E', 0312 }, { '^', 'e', 0352 },
1107                         { '"', 'E', 0313 }, { '"', 'e', 0353 },
1108                         { '`', 'I', 0314 }, { '`', 'i', 0354 },
1109                         { '\'', 'I', 0315 }, { '\'', 'i', 0355 },
1110                         { '^', 'I', 0316 }, { '^', 'i', 0356 },
1111                         { '"', 'I', 0317 }, { '"', 'i', 0357 },
1112                         { '-', 'D', 0320 }, { '-', 'd', 0360 },
1113                         { '~', 'N', 0321 }, { '~', 'n', 0361 },
1114                         { '`', 'O', 0322 }, { '`', 'o', 0362 },
1115                         { '\'', 'O', 0323 }, { '\'', 'o', 0363 },
1116                         { '^', 'O', 0324 }, { '^', 'o', 0364 },
1117                         { '~', 'O', 0325 }, { '~', 'o', 0365 },
1118                         { '"', 'O', 0326 }, { '"', 'o', 0366 },
1119                         { '/', 'O', 0330 }, { '/', 'o', 0370 },
1120                         { '`', 'U', 0331 }, { '`', 'u', 0371 },
1121                         { '\'', 'U', 0332 }, { '\'', 'u', 0372 },
1122                         { '^', 'U', 0333 }, { '^', 'u', 0373 },
1123                         { '"', 'U', 0334 }, { '"', 'u', 0374 },
1124                         { '\'', 'Y', 0335 }, { '\'', 'y', 0375 },
1125                         { 'T', 'H', 0336 }, { 't', 'h', 0376 },
1126                         { 's', 's', 0337 }, { '"', 'y', 0377 },
1127                         { 's', 'z', 0337 }, { 'i', 'j', 0377 }
1128                 };
1129                 int i;
1130                 for(i=0; i<68; i++) {
1131                         struct ccc p = def_latin1_composes[i];
1132                         compose(p.c1, p.c2, p.c3);
1133                 }
1134         }
1135 }
1136
1137 /*
1138  * mktable.c
1139  *
1140  */
1141 static char *modifiers[8] = {
1142     "shift", "altgr", "ctrl", "alt", "shl", "shr", "ctl", "ctr"
1143 };
1144
1145 static char *mk_mapname(char mod) {
1146     static char buf[60];
1147     int i;
1148
1149     if (!mod)
1150       return "plain";
1151     buf[0] = 0;
1152     for (i=0; i<8; i++)
1153       if (mod & (1<<i)) {
1154           if (buf[0])
1155             strcat(buf, "_");
1156           strcat(buf, modifiers[i]);
1157       }
1158     return buf;
1159 }
1160
1161
1162 static void
1163 outchar (unsigned char c, int comma) {
1164         printf("'");
1165         printf((c == '\'' || c == '\\') ? "\\%c" : isgraph(c) ? "%c"
1166                : "\\%03o", c);
1167         printf(comma ? "', " : "'");
1168 }
1169
1170 static void
1171 mktable () {
1172         int i, imax, j;
1173
1174         u_char *p;
1175         int maxfunc;
1176         unsigned int keymap_count = 0;
1177
1178         printf(
1179 /* not to be translated... */
1180 "/* Do not edit this file! It was automatically generated by   */\n");
1181         printf(
1182 "/*    loadkeys --mktable defkeymap.map > defkeymap.c          */\n\n");
1183         printf("#include <linux/types.h>\n");
1184         printf("#include <linux/keyboard.h>\n");
1185         printf("#include <linux/kd.h>\n\n");
1186
1187         for (i = 0; i < MAX_NR_KEYMAPS; i++)
1188           if (key_map[i]) {
1189               keymap_count++;
1190               if (i)
1191                    printf("static ");
1192               printf("u_short %s_map[NR_KEYS] = {", mk_mapname(i));
1193               for (j = 0; j < NR_KEYS; j++) {
1194                   if (!(j % 8))
1195                     printf("\n");
1196                   printf("\t0x%04x,", U((key_map[i])[j]));
1197               }
1198               printf("\n};\n\n");
1199           }
1200
1201         for (imax = MAX_NR_KEYMAPS-1; imax > 0; imax--)
1202           if (key_map[imax])
1203             break;
1204         printf("ushort *key_maps[MAX_NR_KEYMAPS] = {");
1205         for (i = 0; i <= imax; i++) {
1206             printf((i%4) ? " " : "\n\t");
1207             if (key_map[i])
1208               printf("%s_map,", mk_mapname(i));
1209             else
1210               printf("0,");
1211         }
1212         if (imax < MAX_NR_KEYMAPS-1)
1213           printf("\t0");
1214         printf("\n};\n\nunsigned int keymap_count = %d;\n\n", keymap_count);
1215
1216 /* uglified just for xgettext - it complains about nonterminated strings */
1217         printf(
1218 "/*\n"
1219 " * Philosophy: most people do not define more strings, but they who do\n"
1220 " * often want quite a lot of string space. So, we statically allocate\n"
1221 " * the default and allocate dynamically in chunks of 512 bytes.\n"
1222 " */\n"
1223 "\n");
1224         for (maxfunc = MAX_NR_FUNC; maxfunc; maxfunc--)
1225           if(func_table[maxfunc-1])
1226             break;
1227
1228         printf("char func_buf[] = {\n");
1229         for (i = 0; i < maxfunc; i++) {
1230             p = func_table[i];
1231             if (p) {
1232                 printf("\t");
1233                 for ( ; *p; p++)
1234                         outchar(*p, 1);
1235                 printf("0, \n");
1236             }
1237         }
1238         if (!maxfunc)
1239           printf("\t0\n");
1240         printf("};\n\n");
1241
1242         printf(
1243 "char *funcbufptr = func_buf;\n"
1244 "int funcbufsize = sizeof(func_buf);\n"
1245 "int funcbufleft = 0;          /* space left */\n"
1246 "\n");
1247
1248         printf("char *func_table[MAX_NR_FUNC] = {\n");
1249         for (i = 0; i < maxfunc; i++) {
1250             if (func_table[i])
1251               printf("\tfunc_buf + %d,\n", func_table[i] - func_buf);
1252             else
1253               printf("\t0,\n");
1254         }
1255         if (maxfunc < MAX_NR_FUNC)
1256           printf("\t0,\n");
1257         printf("};\n");
1258
1259         printf("\nstruct kbdiacr accent_table[MAX_DIACR] = {\n");
1260         for (i = 0; i < accent_table_size; i++) {
1261                 printf("\t{");
1262                 outchar(accent_table[i].diacr, 1);
1263                 outchar(accent_table[i].base, 1);
1264                 outchar(accent_table[i].result, 0);
1265                 printf("},");
1266                 if(i%2) printf("\n");
1267         }
1268         if(i%2) printf("\n");
1269         printf("};\n\n");
1270         printf("unsigned int accent_table_size = %d;\n",
1271                accent_table_size);
1272
1273         exit(0);
1274 }
1275
1276 static void
1277 bkeymap () {
1278         int i, j;
1279
1280         u_char *p;
1281         char flag, magic[] = "bkeymap";
1282         unsigned short v;
1283
1284         if (write(1, magic, 7) == -1)
1285                 goto fail;
1286         for (i = 0; i < MAX_NR_KEYMAPS; i++) {
1287                 flag = key_map[i] ? 1 : 0;
1288                 if (write(1, &flag, 1) == -1)
1289                         goto fail;
1290         }
1291         for (i = 0; i < MAX_NR_KEYMAPS; i++) {
1292                 if (key_map[i]) {
1293                         for (j = 0; j < NR_KEYS / 2; j++) {
1294                                 v = key_map[i][j];
1295                                 if (write(1, &v, 2) == -1)
1296                                         goto fail;
1297                         }
1298                 }
1299         }
1300         exit(0);
1301 fail:   fprintf(stderr, _("Error writing map to file\n"));
1302         exit(1);
1303 }