1 /* This standalone utility program constructs the function, key and command
2 * binding tables for vile. The input is a data file containing the
3 * desired default relationships among the three entities. Output
4 * is nebind.h, neproto.h, nefunc.h, and nename.h, all of which are then
5 * included in main.c
6 *
7 * Copyright (c) 1990 by Paul Fox
8 * Copyright (c) 1995-2021 by Paul Fox and Thomas Dickey
9 *
10 * See the file "cmdtbl" for input data formats, and "estruct.h" for
11 * the output structures.
12 *
13 * Heavily modified/enhanced to also generate the table of mode and variable
14 * names and their #define "bindings", based on input from the file modetbl,
15 * by Tom Dickey, 1993. -pgf
16 *
17 *
18 * $Id: mktbls.c,v 1.200 2021/03/22 23:21:55 tom Exp $
19 *
20 */
21
22 /* stuff borrowed/adapted from estruct.h */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #undef DOALLOC /* since we're not linking with trace.c */
27 #else /* !defined(HAVE_CONFIG_H) */
28
29 /* Note: VAX-C doesn't recognize continuation-line in ifdef lines */
30 # ifdef vms
31 # define HAVE_STDLIB_H 1
32 # endif
33
34 /* pc-stuff */
35 # if defined(__TURBOC__) || defined(__WATCOMC__) || defined(__GO32__) || defined(__IBMC__) || defined(_WIN32)
36 # define HAVE_STDLIB_H 1
37 # endif
38
39 #endif /* !defined(HAVE_CONFIG_H) */
40
41 #if defined(WIN32)
42 #include "w32vile.h"
43 #endif
44
45 #ifndef SYS_VMS
46 #define SYS_VMS 0
47 #endif
48
49 #ifndef HAVE_CONFIG_H
50 # define HAVE_STDLIB_H 1
51 #endif
52
53 #ifndef HAVE_STDLIB_H
54 # define HAVE_STDLIB_H 0
55 #endif
56
57 #if HAVE_STDLIB_H
58 #include <stdlib.h>
59 #else
60 # if !defined(HAVE_CONFIG_H) || defined(MISSING_EXTERN_MALLOC)
61 extern char *malloc(unsigned int len);
62 # endif
63 # if !defined(HAVE_CONFIG_H) || defined(MISSING_EXTERN_FREE)
64 extern void free(char *ptr);
65 # endif
66 #endif
67
68 /*----------------------------------------------------------------------------*/
69 #include <stdio.h>
70 #include <ctype.h>
71 #include <string.h>
72 #include <setjmp.h>
73
74 #ifndef DOALLOC
75 #define DOALLOC 0
76 #endif
77
78 #if DOALLOC
79 #include "trace.h"
80 #endif
81
82 #ifndef GCC_NORETURN
83 #define GCC_NORETURN /*nothing */
84 #endif
85
86 #ifndef NO_LEAKS
87 #define NO_LEAKS 0
88 #endif
89
90 /* argument for 'exit()' or '_exit()' */
91 #if SYS_VMS
92 #include <stsdef.h>
93 #define GOODEXIT (STS$M_INHIB_MSG | STS$K_SUCCESS)
94 #define BADEXIT (STS$M_INHIB_MSG | STS$K_ERROR)
95 #else
96 #define GOODEXIT 0
97 #define BADEXIT 1
98 #endif
99
100 #define ENUM_PREFIX "vile_"
101
102 #define TABLESIZE(v) (sizeof(v)/sizeof(v[0]))
103
104 #ifndef OPT_EXEC_MACROS
105 #define OPT_EXEC_MACROS 40
106 #endif
107
108 /*--------------------------------------------------------------------------*/
109
110 #define MAX_BIND 4 /* maximum # of key-binding types */
111 #define MAX_PARSE 5 /* maximum # of tokens on line */
112 #define LEN_BUFFER 220 /* nominal buffer-length */
113 #define LEN_FIELD ((LEN_BUFFER-1)/2)
114 #define MAX_BUFFER (LEN_BUFFER*10)
115 #define LEN_CHRSET 256 /* total # of chars in set (ascii) */
116
117 /* FIXME: why not use <ctype.h> ? */
118 #define DIFCNTRL 0x40
119 #define tocntrl(c) ((c)^DIFCNTRL)
120 #define toalpha(c) ((c)^DIFCNTRL)
121 #define isUpper(c) ((c) >= 'A' && (c) <= 'Z')
122 #define isLower(c) ((c) >= 'a' && (c) <= 'z')
123 #define isboolean(c) ((c) == 'b' || (c) == 'M')
124
125 #ifndef TRUE
126 #define TRUE (1)
127 #define FALSE (0)
128 #endif
129
130 #define EOS '\0'
131
132 #define L_CURL '{'
133 #define R_CURL '}'
134
135 #define Fprintf (void)fprintf
136 #define Sprintf (void)sprintf
137
138 #ifdef MISSING_EXTERN_FPRINTF
139 extern int fprintf(FILE *fp, const char *fmt, ...);
140 #endif
141
142 #define SaveEndif(head) InsertOnEnd(&head, "#endif")
143
144 #define FreeIfNeeded(p) if (p != 0) { free(p); p = 0; }
145
146 /*--------------------------------------------------------------------------*/
147
148 typedef struct stringl {
149 char *Name; /* stores primary-data */
150 char *Func; /* stores secondary-data */
151 char *Data; /* associated data, if any */
152 char *Cond; /* stores ifdef-flags */
153 char *Note; /* stores comment, if any */
154 char *Flag; /* stores execution flags, if any */
155 struct stringl *nst;
156 } LIST;
157
158 static char Blank[] =
159 {0};
160
161 static LIST *all_names;
162 static LIST *all_aliases;
163 static LIST *all_kbind; /* data for kbindtbl[] */
164 static LIST *all_w32bind; /* w32 data for kbindtbl[] */
165 static LIST *all_funcs; /* data for extern-lines in neproto.h */
166 static LIST *all__FUNCs; /* data for {}-lines in nefunc.h */
167 static LIST *all__CMDFs; /* data for extern-lines in nefunc.h */
168 static LIST *all_statevars;
169 static LIST *all_ufuncs;
170 static LIST *all_fsms; /* FSM tables */
171 static LIST *all_majors; /* list of predefined major modes */
172 static LIST *all_modes; /* data for name-completion of modes */
173 static LIST *all_submodes; /* data for name-completion of submodes */
174 static LIST *all_gmodes; /* data for GLOBAL modes */
175 static LIST *all_mmodes; /* data for MAJOR modes */
176 static LIST *all_qmodes; /* data for QUALIFIER modes */
177 static LIST *all_bmodes; /* data for BUFFER modes */
178 static LIST *all_wmodes; /* data for WINDOW modes */
179
180 static GCC_NORETURN void badfmt(const char *);
181 static void save_all_modes(const char *type, char *normal, const char
182 *abbrev, const char *cond);
183 static void save_all_submodes(const char *type, char *normal, const char
184 *abbrev, char *cond);
185
186 /* definitions for sections of cmdtbl */
187 typedef enum {
188 SECT_CMDS = 0
189 ,SECT_FUNC
190 ,SECT_VARS
191 ,SECT_GBLS
192 ,SECT_MAJR
193 ,SECT_QUAL
194 ,SECT_BUFF
195 ,SECT_WIND
196 ,SECT_FSMS
197 ,SECT_ABBR
198 } SECTIONS;
199
200 /* definitions for indices to 'asciitbl[]' vs 'kbindtbl[]' */
201 #define ASCIIBIND 0
202 #define CTLXBIND 1
203 #define CTLABIND 2
204 #define SPECBIND 3
205
206 static char *bindings[LEN_CHRSET];
207 static char *conditions[LEN_CHRSET];
208
209 static const char *tblname[MAX_BIND] =
210 {
211 "asciitbl",
212 "ctlxtbl",
213 "metatbl",
214 "spectbl"
215 };
216
217 static const char *prefname[MAX_BIND] =
218 {
219 "",
220 "CTLX|",
221 "CTLA|",
222 "SPEC|"
223 };
224
225 static char *fsm_uc_name;
226 static char *fsm_lc_name;
227 static char *inputfile;
228 static int l = 0;
229 static FILE *cmdtbl;
230 static FILE *nebind;
231 static FILE *neexec;
232 static FILE *neprot;
233 static FILE *nefunc;
234 static FILE *nename;
235 static FILE *nevars;
236 static FILE *nemode;
237 static FILE *nefkeys;
238 static FILE *nefsms;
239 static jmp_buf my_top;
240
241 /******************************************************************************/
242 static char *
my_strncpy0(char * dest,const char * src,size_t destlen)243 my_strncpy0(char *dest, const char *src, size_t destlen)
244 {
245 if (dest != 0 && src != 0 && destlen != 0) {
246 (void) strncpy(dest, src, destlen);
247 dest[destlen - 1] = EOS;
248 }
249 return dest;
250 }
251
252 /*
253 * This is probably more efficient for copying short strings into a large
254 * fixed-size buffer, because strncpy always zero-pads the destination to
255 * the given length.
256 */
257 static char *
my_strncpy(char * dest,const char * src,size_t destlen)258 my_strncpy(char *dest, const char *src, size_t destlen)
259 {
260 size_t srclen = (src != 0) ? (strlen(src) + 1) : 0;
261 return ((srclen > destlen)
262 ? my_strncpy0(dest, src, destlen)
263 : my_strncpy0(dest, src, srclen));
264 }
265
266 static char *
my_strncat(char * dest,const char * src,size_t destlen)267 my_strncat(char *dest, const char *src, size_t destlen)
268 {
269 size_t srclen = (src != 0) ? (strlen(src) + 1) : 0;
270 size_t oldlen = strlen(dest);
271
272 if (srclen > (destlen - oldlen))
273 srclen = (destlen - oldlen);
274
275 (void) my_strncpy0(dest + oldlen, src, srclen);
276 return dest;
277 }
278
279 /******************************************************************************/
280 static int
toUpper(int c)281 toUpper(int c)
282 {
283 return toupper((c) & 0xff);
284 }
285
286 static int
toLower(int c)287 toLower(int c)
288 {
289 return tolower((c) & 0xff);
290 }
291
292 static int
isSpace(int c)293 isSpace(int c)
294 {
295 return c == ' ' || c == '\t' || c == '\n';
296 }
297
298 static int
isPrint(int c)299 isPrint(int c)
300 {
301 return c >= ' ' && c < 0x7f;
302 }
303
304 static char *
lowercase(char * s)305 lowercase(char *s)
306 {
307 char *base = s;
308 while (*s != 0) {
309 *s = (char) toLower(*s);
310 ++s;
311 }
312 return base;
313 }
314
315 /******************************************************************************/
316 static void
badfmt(const char * s)317 badfmt(const char *s)
318 {
319 Fprintf(stderr, "\"%s\", line %d: bad format:", inputfile, l);
320 Fprintf(stderr, "\t%s\n", s);
321 longjmp(my_top, 1);
322 }
323
324 static void
badfmt2(const char * s,int col)325 badfmt2(const char *s, int col)
326 {
327 char temp[MAX_BUFFER];
328 Sprintf(temp, "%s (column %d)", s, col);
329 badfmt(temp);
330 }
331
332 /******************************************************************************/
333 static void *
Alloc(size_t len)334 Alloc(size_t len)
335 {
336 void *pointer = calloc(len, sizeof(char));
337 if (pointer == 0)
338 badfmt("bug: not enough memory");
339 return pointer;
340 }
341
342 static char *
StrAlloc(const char * s)343 StrAlloc(const char *s)
344 {
345 return strcpy(Alloc(strlen(s) + 1), s);
346 }
347
348 static LIST *
ListAlloc(void)349 ListAlloc(void)
350 {
351 return (LIST *) Alloc(sizeof(LIST));
352 }
353
354 static void
free_LIST(LIST ** p)355 free_LIST(LIST ** p)
356 {
357 LIST *q;
358
359 while ((q = *p) != 0) {
360 *p = q->nst;
361 if (q->Name != Blank)
362 FreeIfNeeded(q->Name);
363 if (q->Func != Blank)
364 FreeIfNeeded(q->Func);
365 if (q->Data != Blank)
366 FreeIfNeeded(q->Data);
367 if (q->Cond != Blank)
368 FreeIfNeeded(q->Cond);
369 if (q->Note != Blank)
370 FreeIfNeeded(q->Note);
371 if (q->Flag != 0)
372 FreeIfNeeded(q->Flag);
373 free((char *) q);
374 }
375 *p = 0;
376 }
377
378 /******************************************************************************/
379 static void
WriteLines(FILE * fp,const char * const * list,int count)380 WriteLines(FILE *fp, const char *const *list, int count)
381 {
382 while (count-- > 0)
383 Fprintf(fp, "%s\n", *list++);
384 }
385 #define write_lines(fp,list) WriteLines(fp, list, (int)TABLESIZE(list))
386
387 /******************************************************************************/
388 static FILE *
OpenHeader(const char * name,char ** argv)389 OpenHeader(const char *name, char **argv)
390 {
391 FILE *fp;
392 static const char *progcreat =
393 "/* %s: this header file was produced automatically by\n\
394 * the %s program, based on input from the file %s\n */\n";
395
396 if ((fp = fopen(name, "w")) == 0) {
397 Fprintf(stderr, "mktbls: couldn't open header file %s\n", name);
398 longjmp(my_top, 1);
399 }
400 Fprintf(fp, progcreat, name, argv[0], argv[1]);
401 return fp;
402 }
403
404 /******************************************************************************/
405 static void
InsertSorted(LIST ** headp,const char * name,const char * func,const char * data,const char * cond,const char * note,const char * flag)406 InsertSorted(
407 LIST ** headp,
408 const char *name,
409 const char *func,
410 const char *data,
411 const char *cond,
412 const char *note,
413 const char *flag)
414 {
415 LIST *n, *p, *q;
416 int r;
417
418 n = ListAlloc();
419 n->Name = StrAlloc(name);
420 n->Func = StrAlloc(func);
421 n->Data = StrAlloc(data);
422 n->Cond = StrAlloc(cond);
423 n->Note = StrAlloc(note);
424 n->Flag = StrAlloc(flag);
425
426 for (p = *headp, q = 0; p != 0; q = p, p = p->nst) {
427 if ((r = strcmp(n->Name, p->Name)) < 0)
428 break;
429 else if (r == 0 && !strcmp(n->Cond, p->Cond)) {
430 printf("name=%s\n", n->Name); /* FIXME */
431 badfmt("duplicate name");
432 }
433 }
434 n->nst = p;
435 if (q == 0)
436 *headp = n;
437 else
438 q->nst = n;
439 }
440
441 static void
InsertOnEnd(LIST ** headp,const char * name)442 InsertOnEnd(LIST ** headp, const char *name)
443 {
444 LIST *n, *p, *q;
445
446 n = ListAlloc();
447 n->Name = StrAlloc(name);
448 n->Func = Blank;
449 n->Data = Blank;
450 n->Cond = Blank;
451 n->Note = Blank;
452
453 for (p = *headp, q = 0; p != 0; q = p, p = p->nst) ;
454
455 n->nst = 0;
456 if (q == 0)
457 *headp = n;
458 else
459 q->nst = n;
460 }
461
462 /******************************************************************************/
463 static char *
append(char * dst,const char * src)464 append(char *dst, const char *src)
465 {
466 (void) strcat(dst, src);
467 return (dst + strlen(dst));
468 }
469
470 static char *
formcond(const char * c1,const char * c2)471 formcond(const char *c1, const char *c2)
472 {
473 static char cond[MAX_BUFFER];
474
475 if (c1[0] && c2[0])
476 Sprintf(cond, "(%s) && (%s)", c1, c2);
477 else if (c1[0] || c2[0])
478 Sprintf(cond, "(%s%s)", c1, c2);
479 else
480 cond[0] = EOS;
481 return cond;
482 }
483
484 static int
LastCol(char * buffer)485 LastCol(char *buffer)
486 {
487 int col = 0, c;
488
489 while ((c = *buffer++) != 0) {
490 if (isPrint(c))
491 col++;
492 else if (c == '\t')
493 col = (col | 7) + 1;
494 }
495 return col;
496 }
497
498 static char *
PadTo(int col,char * buffer)499 PadTo(int col, char *buffer)
500 {
501 int any = 0;
502 int len = (int) strlen(buffer);
503 int now;
504 char with;
505
506 for (;;) {
507 if ((now = LastCol(buffer)) >= col) {
508 if (any)
509 break;
510 else
511 with = ' ';
512 } else if (col - now > 2)
513 with = '\t';
514 else
515 with = ' ';
516
517 buffer[len++] = with;
518 buffer[len] = EOS;
519 any++;
520 }
521 return buffer;
522 }
523
524 static int
two_conds(int c,char * cond)525 two_conds(int c, char *cond)
526 {
527 /* return true if both bindings have different
528 conditions associated with them */
529 return (cond[0] != '\0' &&
530 conditions[c] != NULL &&
531 strcmp(cond, conditions[c]) != '\0');
532 }
533
534 static void
set_binding(int btype,int c,char * cond,char * func)535 set_binding(int btype, int c, char *cond, char *func)
536 {
537 char name[MAX_BUFFER];
538
539 if (btype != ASCIIBIND) {
540 if (c < ' ') {
541 Sprintf(name, "%stocntrl('%c')",
542 prefname[btype],
543 toalpha(c));
544 } else if (c >= 0x80) {
545 Sprintf(name, "%s0x%x",
546 prefname[btype], c);
547 } else {
548 Sprintf(name, "%s'%s%c'",
549 prefname[btype],
550 (c == '\'' || c == '\\') ? "\\" : "",
551 c);
552 }
553 InsertSorted(&all_kbind, name, func, "", cond, "", "");
554 } else {
555 if (bindings[c] != NULL) {
556 if (!two_conds(c, cond))
557 badfmt("duplicate key binding");
558 free(bindings[c]);
559 }
560 bindings[c] = StrAlloc(func);
561 if (cond[0]) {
562 FreeIfNeeded(conditions[c]);
563 conditions[c] = StrAlloc(cond);
564 } else {
565 conditions[c] = NULL;
566 }
567 }
568 }
569
570 /******************************************************************************/
571 /* returns the number of non-comment tokens parsed, with a list of
572 * tokens (0=comment) as a side-effect. Note that quotes are removed
573 * from the token, so we have to have them only in the first token! */
574 static int
Parse(char * input,char ** vec)575 Parse(char *input, char **vec)
576 {
577 int expecting = TRUE, count = 0, quote = 0, n, c;
578
579 for (c = 0; c < MAX_PARSE; c++)
580 vec[c] = Blank;
581 for (c = (int) strlen(input); c > 0 && isSpace(input[c - 1]); c--)
582 input[c - 1] = EOS;
583
584 for (n = 0; (c = input[n++]) != EOS;) {
585 if (quote) {
586 if (c == quote) {
587 quote = 0;
588 if (input[n] && !isSpace(input[n]))
589 badfmt2("expected blank", n);
590 input[n - 1] = EOS;
591 }
592 } else {
593 if ((c == '"') || (c == '\'')) {
594 quote = c;
595 } else if (c == '<') {
596 c = quote = '>';
597 } else if (isSpace(c)) {
598 input[n - 1] = EOS;
599 expecting = TRUE;
600 } else if (c == '#') {
601 while (isSpace(input[n]))
602 n++;
603 vec[0] = input + n;
604 break;
605 }
606 if (expecting && !isSpace(c)) {
607 if (count + 1 >= MAX_PARSE)
608 break;
609 vec[++count] = input + n - ((c != quote) ? 1 : 0);
610 expecting = FALSE;
611 }
612 }
613 }
614 return count;
615 }
616
617 /******************************************************************************/
618 static const char *lastIfdef;
619
620 static void
BeginIf(void)621 BeginIf(void)
622 {
623 lastIfdef = 0;
624 }
625
626 static void
FlushIf(FILE * fp)627 FlushIf(FILE *fp)
628 {
629 if (lastIfdef != 0) {
630 Fprintf(fp, "#endif\n");
631 lastIfdef = 0;
632 }
633 }
634
635 static void
WriteIf(FILE * fp,const char * cond)636 WriteIf(FILE *fp, const char *cond)
637 {
638 if (cond == 0)
639 cond = "";
640 if (cond[0] != EOS && strcmp(cond, "1")) {
641 if (lastIfdef != 0) {
642 if (!strcmp(lastIfdef, cond))
643 return;
644 FlushIf(fp);
645 }
646 Fprintf(fp, "#if %s\n", lastIfdef = cond);
647 } else
648 FlushIf(fp);
649 }
650
651 /******************************************************************************/
652 /* get abbreviation by taking the uppercase chars only */
653 static char *
AbbrevMode(char * src)654 AbbrevMode(char *src)
655 {
656 char *dst = StrAlloc(src);
657 char *s = src, *d = dst;
658 while (*s) {
659 if (isUpper(*s))
660 *d++ = (char) toLower(*s);
661 s++;
662 }
663 *d = EOS;
664 return dst;
665 }
666
667 /* get name, converted to lowercase */
668 static char *
NormalMode(char * src)669 NormalMode(char *src)
670 {
671 char *dst = StrAlloc(src);
672 char *s = dst;
673
674 while (*s) {
675 if (isUpper(*s))
676 *s = (char) toLower(*s);
677 s++;
678 }
679 return dst;
680 }
681
682 /* given single-char type-key (cf: Mode2Key), return define-string */
683 static const char *
c2TYPE(int c)684 c2TYPE(int c)
685 {
686 const char *value;
687
688 switch (c) {
689 case 'b':
690 value = "BOOL";
691 break;
692 case 'e':
693 value = "ENUM";
694 break;
695 case 'i':
696 value = "INT";
697 break;
698 case 's':
699 value = "STRING";
700 break;
701 case 'x':
702 value = "REGEX";
703 break;
704 default:
705 value = "?";
706 }
707 return value;
708 }
709
710 static int
is_majormode(const char * name)711 is_majormode(const char *name)
712 {
713 LIST *p;
714
715 for (p = all_mmodes; p != 0; p = p->nst) {
716 if (!strcmp(name, p->Name))
717 return TRUE;
718 }
719 return FALSE;
720 }
721
722 /* check that the mode-name won't be illegal */
723 static void
CheckModes(char * name)724 CheckModes(char *name)
725 {
726 if (!strncmp(name, "no", (size_t) 2))
727 badfmt("illegal mode-name");
728 }
729
730 static char *
AllocKey(char * normal,int type,char * abbrev)731 AllocKey(char *normal, int type, char *abbrev)
732 {
733 char *tmp = Alloc(4 + strlen(normal) + strlen(abbrev));
734 Sprintf(tmp, "%s\n%c\n%s", normal, type, abbrev);
735 return tmp;
736 }
737
738 /* make a sort-key for mode-name */
739 static char *
Mode2Key(char * type,char * name,char * cond,int submode)740 Mode2Key(char *type, char *name, char *cond, int submode)
741 {
742 int c;
743 char *abbrev = AbbrevMode(name);
744 char *normal = NormalMode(name);
745 char *tmp;
746
747 CheckModes(normal);
748 CheckModes(abbrev);
749
750 switch (c = *type) {
751 case 'b':
752 case 'e':
753 case 'i':
754 case 's':
755 break;
756 case 'r':
757 c = 'x'; /* make this sort after strings */
758 }
759
760 save_all_modes(type, normal, abbrev, cond);
761 if (submode)
762 save_all_submodes(type, normal, abbrev, cond);
763
764 tmp = AllocKey(normal, c, abbrev);
765 #if NO_LEAKS
766 free(normal);
767 free(abbrev);
768 #endif
769 return tmp;
770 }
771
772 /* make a sort-key for state-variables */
773 static char *
Vars2Key(char * type,char * name,char * cond)774 Vars2Key(char *type, char *name, char *cond)
775 {
776 int c;
777 char *abbrev = AbbrevMode(name);
778 char *normal = NormalMode(name);
779 char *tmp;
780
781 CheckModes(normal);
782 CheckModes(abbrev);
783
784 switch (c = *type) {
785 case 'b':
786 case 'e':
787 case 'i':
788 case 's':
789 break;
790 case 'r':
791 c = 'x'; /* make this sort after strings */
792 }
793
794 /* insert into 'all_modes' to provide for common name-completion
795 * table, and into 'all_statevars' to get name/index correspondence.
796 */
797 InsertSorted(&all_modes, name, "state", "",
798 formcond("OPT_EVAL", cond),
799 "",
800 "");
801
802 tmp = AllocKey(normal, c, abbrev);
803 #if NO_LEAKS
804 free(normal);
805 free(abbrev);
806 #endif
807 return tmp;
808 }
809
810 /* converts a mode-name to a legal (hopefully unique!) symbol */
811 static char *
Name2Symbol(char * name)812 Name2Symbol(char *name)
813 {
814 char *base, *dst;
815 char c;
816
817 /* allocate enough for adjustment in 'Name2Address()' */
818 /* "+ 10" for comfort */
819 base = dst = Alloc(strlen(name) + 10);
820
821 *dst++ = 's';
822 *dst++ = '_';
823 while ((c = *name++) != EOS) {
824 if (c == '-')
825 c = '_';
826 *dst++ = c;
827 }
828 *dst++ = '_';
829 *dst++ = '_';
830 *dst = EOS;
831 return base;
832 }
833
834 /* converts a mode-name & type to a reference to string-value */
835 static char *
Name2Address(char * name,char * type)836 Name2Address(char *name, char *type)
837 {
838 /* "+ 10" for comfort */
839 size_t len = strlen(name) + 10;
840 char *base;
841 char *temp;
842
843 temp = Name2Symbol(name);
844 if (strlen(temp) + 1 + (size_t) (isboolean(*type) ? 4 : 0) > len)
845 badfmt("bug: buffer overflow in Name2Address");
846
847 base = Alloc(len);
848 (void) strcpy(base, temp);
849 if (isboolean(*type))
850 (void) strcat(strcat(strcpy(base + 2, "no"), temp + 2), "+2");
851 free(temp);
852 return base;
853 }
854
855 /* generate the index-struct (used for deriving ifdef-able index definitions) */
856 static void
WriteIndexStruct(FILE * fp,LIST * p,const char * ppref)857 WriteIndexStruct(FILE *fp, LIST * p, const char *ppref)
858 {
859 char *s, temp[MAX_BUFFER], line[MAX_BUFFER], *vec[MAX_PARSE];
860 int count = 0;
861
862 BeginIf();
863 Fprintf(fp, "typedef\tenum\t%c\n", L_CURL);
864 /*
865 * The first symbol is unused; it is a placeholder in case the first value
866 * is ifdef'd out.
867 */
868 Fprintf(fp, "\tDUMMY_%c_VALUES = -1\n", *ppref);
869 for (; p != 0; p = p->nst, count++) {
870 WriteIf(fp, p->Cond);
871 (void) Parse(my_strncpy(line, p->Name, sizeof(line)), vec);
872 Sprintf(temp, "\t,%s%s", ENUM_PREFIX, s = Name2Symbol(vec[1]));
873 free(s);
874 if (p->Note[0]) {
875 (void) PadTo(32, temp);
876 Sprintf(temp + strlen(temp), "/* %s */", p->Note);
877 }
878 Fprintf(fp, "%s\n", temp);
879 }
880 FlushIf(fp);
881
882 Sprintf(temp, "\t,NUM_%c_VALUES", *ppref);
883 (void) PadTo(32, temp);
884 Sprintf(temp + strlen(temp), "/* TABLESIZE(%c_valnames) -- %s */\n",
885 toLower(*ppref), ppref);
886 Fprintf(nemode, "%s", temp);
887
888 Fprintf(fp, "\t%c Index%s;\n\n", R_CURL, ppref);
889 }
890
891 /* generate the index-definitions */
892 static void
WriteModeDefines(LIST * p,const char * ppref)893 WriteModeDefines(LIST * p, const char *ppref)
894 {
895 char temp[MAX_BUFFER], line[MAX_BUFFER], *vec[MAX_PARSE];
896 int count = 0;
897 char *s;
898 BeginIf();
899
900 for (; p != 0; p = p->nst, count++) {
901 (void) Parse(my_strncpy(line, p->Name, sizeof(line)), vec);
902 Sprintf(temp, "#define %.1s%s%s",
903 (*ppref == 'B') ? "" : ppref,
904 (*vec[2] == 'b') ? "MD" : "VAL_",
905 p->Func);
906 (void) PadTo(24, temp);
907 WriteIf(nemode, p->Cond);
908 Sprintf(temp + strlen(temp), "%s%s",
909 ENUM_PREFIX, s = Name2Symbol(vec[1]));
910 free(s);
911 Fprintf(nemode, "%s\n", temp);
912 }
913
914 Fprintf(nemode, "\n");
915 FlushIf(nemode);
916
917 Fprintf(nemode, "#define MAX_%c_VALUES\t%d\n\n", *ppref, count);
918 }
919
920 static void
WriteModeSymbols(LIST * p)921 WriteModeSymbols(LIST * p)
922 {
923 char temp[MAX_BUFFER], line[MAX_BUFFER];
924 char *vec[MAX_PARSE], *s;
925
926 /* generate the symbol-table */
927 BeginIf();
928 while (p != 0) {
929 WriteIf(nemode, p->Cond);
930 (void) Parse(my_strncpy(line, p->Name, sizeof(line)), vec);
931 Sprintf(temp, "\t%c %s,",
932 L_CURL, s = Name2Address(vec[1], vec[2]));
933 (void) PadTo(32, temp);
934 free(s);
935 s = 0;
936
937 Sprintf(temp + strlen(temp), "%s,",
938 (*vec[3]
939 ? (s = Name2Address(vec[3], vec[2]))
940 : "\"X\""));
941 (void) PadTo(48, temp);
942 if (s != 0)
943 free(s);
944
945 Sprintf(temp + strlen(temp), "VALTYPE_%s,", c2TYPE(*vec[2]));
946 (void) PadTo(64, temp);
947 if (!strcmp(p->Data, "0"))
948 (void) my_strncat(temp, "(ChgdFunc)0 },", sizeof(temp));
949 else
950 Sprintf(temp + strlen(temp), "%s },", p->Data);
951 Fprintf(nemode, "%s\n", temp);
952 p = p->nst;
953 }
954 FlushIf(nemode);
955 }
956
957 /******************************************************************************/
958 static void
save_all_modes(const char * type,char * normal,const char * abbrev,const char * cond)959 save_all_modes(
960 const char *type,
961 char *normal,
962 const char *abbrev,
963 const char *cond)
964 {
965 if (isboolean(*type)) {
966 char t_normal[LEN_BUFFER], t_abbrev[LEN_BUFFER];
967 my_strncat(strcpy(t_normal, "no"), normal, sizeof(t_normal));
968 if (*abbrev) {
969 my_strncat(strcpy(t_abbrev, "no"), abbrev, sizeof(t_abbrev));
970 } else {
971 strcpy(t_abbrev, "");
972 }
973 save_all_modes("Bool", t_normal, t_abbrev, cond);
974 }
975 InsertSorted(&all_modes, normal, type, "", cond, "", "");
976 if (*abbrev && strcmp(normal, abbrev)) {
977 InsertSorted(&all_modes, abbrev, type, "", cond, "", "");
978 }
979 }
980
981 static void
dump_all_modes(void)982 dump_all_modes(void)
983 {
984 static const char *const top[] =
985 {
986 "",
987 "#ifdef realdef",
988 "/*",
989 " * List of strings shared between all_modes, b_valnames and w_valnames",
990 " */",
991 "static const char",
992 };
993 static const char *const middle[] =
994 {
995 "\ts_NULL[] = \"\";",
996 "#endif /* realdef */",
997 "",
998 "#ifdef realdef",
999 "DECL_EXTERN_CONST(char *const all_modes[]) = {",
1000 };
1001 static const char *const bottom[] =
1002 {
1003 "\tNULL\t/* ends table */",
1004 "};",
1005 "#else",
1006 "extern const char *const all_modes[];",
1007 "#endif /* realdef */",
1008 };
1009 char temp[MAX_BUFFER], *s;
1010 LIST *p, *q;
1011
1012 InsertSorted(&all_modes, "all", "?", "", "", "", "");
1013 write_lines(nemode, top);
1014 BeginIf();
1015 for (p = all_modes; p; p = p->nst) {
1016 if (!isboolean(p->Func[0])) {
1017 for (q = p->nst; q != 0; q = q->nst)
1018 if (!isboolean(q->Func[0]))
1019 break;
1020 WriteIf(nemode, p->Cond);
1021 Sprintf(temp, "\t%s[]", s = Name2Symbol(p->Name));
1022 (void) PadTo(32, temp);
1023 free(s);
1024 Sprintf(temp + strlen(temp), "= \"%s\",", p->Name);
1025 (void) PadTo(64, temp);
1026 Fprintf(nemode, "%s/* %s */\n", temp, p->Func);
1027 }
1028 }
1029 FlushIf(nemode);
1030
1031 write_lines(nemode, middle);
1032 for (p = all_modes; p; p = p->nst) {
1033 if (is_majormode(p->Name))
1034 continue;
1035 WriteIf(nemode, p->Cond);
1036 Fprintf(nemode, "\t%s,\n", s = Name2Address(p->Name, p->Func));
1037 free(s);
1038 }
1039 FlushIf(nemode);
1040
1041 write_lines(nemode, bottom);
1042 }
1043
1044 /******************************************************************************/
1045 static void
save_bindings(char * s,char * func,char * cond)1046 save_bindings(char *s, char *func, char *cond)
1047 {
1048 int btype, c, highbit;
1049
1050 btype = ASCIIBIND;
1051
1052 if (*s == '^' && *(s + 1) == 'A' && *(s + 2) == '-') {
1053 btype = CTLABIND;
1054 s += 3;
1055 } else if (*s == 'F' && *(s + 1) == 'N' && *(s + 2) == '-') {
1056 btype = SPECBIND;
1057 s += 3;
1058 } else if (*s == '^' && *(s + 1) == 'X' && *(s + 2) == '-') {
1059 btype = CTLXBIND;
1060 s += 3;
1061 }
1062 if (*s == 'M' && *(s + 1) == '-') {
1063 highbit = 0x80;
1064 s += 2;
1065 } else {
1066 highbit = 0;
1067 }
1068
1069 if (*s == '\\') { /* try for an octal value */
1070 c = 0;
1071 while (*++s < '8' && *s >= '0')
1072 c = (c * 8) + *s - '0';
1073 if (c >= LEN_CHRSET)
1074 badfmt("octal character too big");
1075 c |= highbit;
1076 set_binding(btype, c, cond, func);
1077 } else if (*s == '^' && (c = *(s + 1)) != EOS) { /* a control char? */
1078 if (c > 'a' && c < 'z')
1079 c = toUpper(c);
1080 c = tocntrl(c);
1081 c |= highbit;
1082 set_binding(btype, c, cond, func);
1083 s += 2;
1084 } else if ((c = *s) != 0) {
1085 c |= highbit;
1086 set_binding(btype, c, cond, func);
1087 s++;
1088 } else {
1089 badfmt("getting binding");
1090 }
1091
1092 if (*s != EOS)
1093 badfmt("got extra characters");
1094 }
1095
1096 static void
dump_bindings(void)1097 dump_bindings(void)
1098 {
1099 char temp[MAX_BUFFER];
1100 const char *sctl, *meta;
1101 int i, c, btype;
1102 LIST *p;
1103
1104 btype = ASCIIBIND;
1105
1106 Fprintf(nebind, "\nconst CMDFUNC *%s[%d] = %c\n",
1107 tblname[btype], LEN_CHRSET, L_CURL);
1108
1109 BeginIf();
1110 for (i = 0; i < LEN_CHRSET; i++) {
1111 WriteIf(nebind, conditions[i]);
1112
1113 sctl = "";
1114 if (i & 0x80)
1115 meta = "meta-";
1116 else
1117 meta = "";
1118 c = i & 0x7f;
1119 if (c < ' ' || c > '~') {
1120 sctl = "ctrl-";
1121 c = toalpha(c);
1122 }
1123
1124 if (bindings[i])
1125 Sprintf(temp, "\t&f_%s,", bindings[i]);
1126 else
1127 Sprintf(temp, "\tNULL,");
1128
1129 Fprintf(nebind, "%s/* %s%s%c */\n", PadTo(32, temp),
1130 meta, sctl, c);
1131 if (conditions[i] != 0)
1132 Fprintf(nebind, "#else\n\tNULL,\n");
1133 FlushIf(nebind);
1134
1135 }
1136 Fprintf(nebind, "%c;\n", R_CURL);
1137
1138 Fprintf(nebind, "\nKBIND kbindtbl[] = %c\n", L_CURL);
1139 BeginIf();
1140 for (p = all_kbind; p; p = p->nst) {
1141 WriteIf(nebind, p->Cond);
1142 Sprintf(temp, "\t%c %s,", L_CURL, p->Name);
1143 PadTo(32, temp);
1144 Sprintf(temp + strlen(temp), "&f_%s", p->Func);
1145 PadTo(56, temp);
1146 Fprintf(nebind, "%sKBIND_LINK(NULL) %c,\n", temp, R_CURL);
1147 }
1148 FlushIf(nebind);
1149 if (all_w32bind) {
1150 BeginIf();
1151 for (p = all_w32bind; p; p = p->nst) {
1152 WriteIf(nebind, p->Cond);
1153 Sprintf(temp, "\t%c %s,", L_CURL, p->Name);
1154 Fprintf(nebind, "%s&f_%s KBIND_LINK(NULL) %c,\n",
1155 PadTo(32, temp), p->Func, R_CURL);
1156 }
1157 FlushIf(nebind);
1158 }
1159
1160 Fprintf(nebind, "\t{ 0, NULL KBIND_LINK(NULL) }\n");
1161 Fprintf(nebind, "%c;\n", R_CURL);
1162
1163 }
1164
1165 /******************************************************************************/
1166 /*
1167 * Construct submode names for the given predefined majormodes
1168 */
1169 static void
dump_majors(void)1170 dump_majors(void)
1171 {
1172 LIST *p, *q;
1173 char norm[LEN_BUFFER], abbr[LEN_BUFFER], type[LEN_BUFFER];
1174 char normal[LEN_BUFFER], abbrev[LEN_BUFFER];
1175 const char *my_cond = "OPT_MAJORMODE";
1176
1177 for (q = all_majors; q; q = q->nst) {
1178 Sprintf(normal, "%smode", q->Name); /* FIXME */
1179 save_all_modes("Major", normal, "", my_cond);
1180 }
1181 for (p = all_mmodes; p; p = p->nst) {
1182 if (sscanf(p->Name, "%s\n%s\n%s", norm, type, abbr) != 3)
1183 continue;
1184 for (q = all_majors; q; q = q->nst) {
1185 Sprintf(normal, "%.*s-%.*s", LEN_FIELD, q->Name, LEN_FIELD, norm);
1186 Sprintf(abbrev, "%s%s", q->Name, abbr);
1187 save_all_modes(c2TYPE(*type), normal, abbrev, my_cond);
1188 }
1189 }
1190 free_LIST(&all_majors);
1191 }
1192
1193 /******************************************************************************/
1194 static void
save_mmodes(char * type,char ** vec)1195 save_mmodes(char *type, char **vec)
1196 {
1197 char *key = Mode2Key(type, vec[1], vec[4], TRUE);
1198
1199 InsertSorted(&all_mmodes, key, vec[2], vec[3], vec[4], vec[0], "");
1200 #if NO_LEAKS
1201 free(key);
1202 #endif
1203 }
1204
1205 static void
dump_mmodes(void)1206 dump_mmodes(void)
1207 {
1208 static const char *const top[] =
1209 {
1210 "",
1211 "#if OPT_MAJORMODE",
1212 "/* major mode flags\t*/",
1213 "/* the indices of M_VALUES.v[] */",
1214 };
1215 static const char *const middle[] =
1216 {
1217 "",
1218 "typedef struct M_VALUES {",
1219 "\t/* each entry is a val, and a ptr to a val */",
1220 "\tstruct VAL mv[MAX_M_VALUES+1];",
1221 "} M_VALUES;",
1222 "",
1223 "#ifdef realdef",
1224 "DECL_EXTERN_CONST(struct VALNAMES m_valnames[MAX_M_VALUES+1]) = {",
1225 };
1226 static const char *const bottom[] =
1227 {
1228 "",
1229 "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
1230 "};",
1231 "#else",
1232 "extern const struct VALNAMES m_valnames[MAX_M_VALUES+1];",
1233 "#endif",
1234 "#endif /* OPT_MAJORMODE */",
1235 };
1236
1237 write_lines(nemode, top);
1238 WriteIndexStruct(nemode, all_mmodes, "Major");
1239 WriteModeDefines(all_mmodes, "Major");
1240 write_lines(nemode, middle);
1241 WriteModeSymbols(all_mmodes);
1242 write_lines(nemode, bottom);
1243 }
1244
1245 /******************************************************************************/
1246 static void
save_abbr_in(LIST ** q,LIST * p,char ** vec)1247 save_abbr_in(LIST ** q, LIST * p, char **vec)
1248 {
1249 char full_name[LEN_BUFFER];
1250 char part_name[LEN_BUFFER];
1251 char type_name[LEN_BUFFER];
1252 int count;
1253
1254 for (; p; p = p->nst) {
1255 *full_name = EOS;
1256 *type_name = EOS;
1257 *part_name = EOS;
1258 count = sscanf(p->Name, "%s\n%s\n%s", full_name, type_name, part_name);
1259 if (count == 2 || (count == 3 && *part_name == EOS)) {
1260 if (!strcmp(full_name, vec[1])) {
1261 free(p->Name);
1262 p->Name = AllocKey(full_name, *type_name, vec[2]);
1263 *q = p;
1264 }
1265 } else if (count == 3) {
1266 if (!strcmp(full_name, vec[1])) {
1267 fprintf(stderr, "\"%s\" already has alias \"%s\"\n",
1268 full_name,
1269 vec[2]);
1270 badfmt("naming conflict");
1271 }
1272 }
1273 }
1274 }
1275
1276 static void
save_abbrs(char ** vec)1277 save_abbrs(char **vec)
1278 {
1279 LIST *p = 0;
1280
1281 save_abbr_in(&p, all_gmodes, vec);
1282 save_abbr_in(&p, all_qmodes, vec);
1283 save_abbr_in(&p, all_bmodes, vec);
1284 save_abbr_in(&p, all_wmodes, vec);
1285 save_abbr_in(&p, all_mmodes, vec);
1286 if (p) {
1287 InsertSorted(&all_modes, vec[2], p->Data, "", p->Cond, "", "");
1288 } else {
1289 fprintf(stderr, "Did not find \"%s\"\n", vec[1]);
1290 longjmp(my_top, 1);
1291 }
1292 }
1293
1294 /******************************************************************************/
1295 static void
save_all_submodes(const char * type,char * normal,const char * abbrev,char * cond)1296 save_all_submodes(
1297 const char *type,
1298 char *normal,
1299 const char *abbrev,
1300 char *cond)
1301 {
1302 if (isboolean(*type)) {
1303 char t_normal[LEN_BUFFER], t_abbrev[LEN_BUFFER];
1304 my_strncat(strcpy(t_normal, "no"), normal, sizeof(t_normal));
1305 if (*abbrev) {
1306 my_strncat(strcpy(t_abbrev, "no"), abbrev, sizeof(t_abbrev));
1307 } else {
1308 strcpy(t_abbrev, "");
1309 }
1310 save_all_submodes("Bool", t_normal, t_abbrev, cond);
1311 }
1312 InsertSorted(&all_submodes, normal, type, "", cond, "", "");
1313 if (*abbrev && strcmp(normal, abbrev)) {
1314 InsertSorted(&all_submodes, abbrev, type, "", cond, "", "");
1315 }
1316 }
1317
1318 static void
dump_all_submodes(void)1319 dump_all_submodes(void)
1320 {
1321 static const char *const top[] =
1322 {
1323 "",
1324 "#if OPT_MAJORMODE",
1325 "#ifdef realdef",
1326 "DECL_EXTERN_CONST(char *const all_submodes[]) = {",
1327 };
1328 static const char *const bottom[] =
1329 {
1330 "\tNULL\t/* ends table */",
1331 "};",
1332 "#else",
1333 "extern const char *const all_submodes[];",
1334 "#endif /* realdef */",
1335 "#endif /* OPT_MAJORMODE */",
1336 };
1337 char *s;
1338 LIST *p;
1339
1340 write_lines(nemode, top);
1341 for (p = all_submodes; p; p = p->nst) {
1342 if (is_majormode(p->Name))
1343 continue;
1344 WriteIf(nemode, p->Cond);
1345 Fprintf(nemode, "\t%s,\n", s = Name2Address(p->Name, p->Func));
1346 free(s);
1347 }
1348 FlushIf(nemode);
1349
1350 write_lines(nemode, bottom);
1351 }
1352
1353 /******************************************************************************/
1354 static void
predefine_submodes(char ** vec,int len)1355 predefine_submodes(char **vec, int len)
1356 {
1357 LIST *p;
1358 int found;
1359 char norm[LEN_BUFFER], type[LEN_BUFFER], abbr[LEN_BUFFER], temp[LEN_BUFFER];
1360
1361 if (len > 1) {
1362 for (p = all_majors, found = FALSE; p; p = p->nst) {
1363 if (!strcmp(p->Name, vec[2])) {
1364 found = TRUE;
1365 break;
1366 }
1367 }
1368 if (!found) {
1369 InsertSorted(&all_majors, vec[2], "", "", "", "", "");
1370 }
1371 if (len > 2) {
1372 for (p = all_bmodes, found = FALSE; p; p = p->nst) {
1373 if (sscanf(p->Name, "%s\n%s\n%s",
1374 norm, type, abbr) == 3
1375 && (!strcmp(norm, vec[3])
1376 || !strcmp(abbr, vec[3]))) {
1377 found = TRUE;
1378 break;
1379 }
1380 }
1381 if (found) {
1382 Sprintf(temp, "%.*s-%.*s", LEN_FIELD, vec[2], LEN_FIELD, norm);
1383 my_strncpy(norm, temp, sizeof(norm));
1384 Sprintf(temp, "%s%s", vec[2], abbr);
1385 my_strncpy(abbr, temp, sizeof(abbr));
1386 save_all_modes(c2TYPE(*type), norm, abbr,
1387 formcond(p->Cond, "OPT_MAJORMODE"));
1388 }
1389 }
1390 }
1391 }
1392
1393 /******************************************************************************/
1394 static void
save_qmodes(char * type,char ** vec)1395 save_qmodes(char *type, char **vec)
1396 {
1397 char *key = Mode2Key(type, vec[1], vec[4], TRUE);
1398 InsertSorted(&all_qmodes, key, vec[2], vec[3], vec[4], vec[0], "");
1399 #if NO_LEAKS
1400 free(key);
1401 #endif
1402 }
1403
1404 static void
dump_qmodes(void)1405 dump_qmodes(void)
1406 {
1407 static const char *const top[] =
1408 {
1409 "",
1410 "/* submode qualifier flags\t*/",
1411 "/* the indices of Q_VALUES.v[] */",
1412 };
1413 static const char *const middle[] =
1414 {
1415 "",
1416 "typedef struct Q_VALUES {",
1417 "\t/* each entry is a val, and a ptr to a val */",
1418 "\tstruct VAL qv[MAX_Q_VALUES+1];",
1419 "} Q_VALUES;",
1420 "",
1421 "#ifdef realdef",
1422 "DECL_EXTERN_CONST(struct VALNAMES q_valnames[MAX_Q_VALUES+1]) = {",
1423 };
1424 static const char *const bottom[] =
1425 {
1426 "",
1427 "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
1428 "};",
1429 "#else",
1430 "extern const struct VALNAMES q_valnames[MAX_Q_VALUES+1];",
1431 "#endif",
1432 };
1433
1434 write_lines(nemode, top);
1435 WriteIndexStruct(nemode, all_qmodes, "Qualifiers");
1436 WriteModeDefines(all_qmodes, "Qualifiers");
1437 write_lines(nemode, middle);
1438 WriteModeSymbols(all_qmodes);
1439 write_lines(nemode, bottom);
1440 }
1441
1442 /******************************************************************************/
1443 static int
ok_submode(char * side_effect)1444 ok_submode(char *side_effect)
1445 {
1446 return strcmp(side_effect, "chgd_major") != 0;
1447 }
1448
1449 static void
save_bmodes(char * type,char ** vec)1450 save_bmodes(char *type, char **vec)
1451 {
1452 char *key = Mode2Key(type, vec[1], vec[4], ok_submode(vec[3]));
1453 InsertSorted(&all_bmodes, key, vec[2], vec[3], vec[4], vec[0], "");
1454 #if NO_LEAKS
1455 free(key);
1456 #endif
1457 }
1458
1459 static void
dump_bmodes(void)1460 dump_bmodes(void)
1461 {
1462 static const char *const top[] =
1463 {
1464 "",
1465 "/* buffer mode flags\t*/",
1466 "/* the indices of B_VALUES.v[] */",
1467 };
1468 static const char *const middle[] =
1469 {
1470 "",
1471 "typedef struct B_VALUES {",
1472 "\t/* each entry is a val, and a ptr to a val */",
1473 "\tstruct VAL bv[MAX_B_VALUES+1];",
1474 "} B_VALUES;",
1475 "",
1476 "#ifdef realdef",
1477 "DECL_EXTERN_CONST(struct VALNAMES b_valnames[]) = {",
1478 };
1479 static const char *const bottom[] =
1480 {
1481 "",
1482 "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
1483 "};",
1484 "#else",
1485 "extern const struct VALNAMES b_valnames[];",
1486 "#endif",
1487 };
1488
1489 write_lines(nemode, top);
1490 WriteIndexStruct(nemode, all_bmodes, "Buffers");
1491 WriteModeDefines(all_bmodes, "Buffers");
1492 write_lines(nemode, middle);
1493 WriteModeSymbols(all_bmodes);
1494 write_lines(nemode, bottom);
1495 }
1496
1497 /******************************************************************************/
1498 static void
start_vars_h(char ** argv)1499 start_vars_h(char **argv)
1500 {
1501 static const char *const head[] =
1502 {
1503 "",
1504 "#include <blist.h>",
1505 "",
1506 "#if OPT_EVAL",
1507 "",
1508 "/*\tstructure to hold temp variables and their definitions\t*/",
1509 "",
1510 "typedef struct UVAR {",
1511 "\tstruct UVAR *next;",
1512 "\tchar *u_name;\t\t/* name of temp variable */",
1513 "\tchar *u_value;\t\t/* value (string) */",
1514 "\tchar u_type;\t\t/* type (normally string) */",
1515 "} UVAR;",
1516 "",
1517 "decl_uninit( UVAR *temp_vars );\t/* temporary variables */",
1518 "",
1519 };
1520
1521 if (!nevars) {
1522 nevars = OpenHeader("nevars.h", argv);
1523 write_lines(nevars, head);
1524 }
1525 }
1526
1527 static void
finish_vars_h(void)1528 finish_vars_h(void)
1529 {
1530 if (nevars)
1531 Fprintf(nevars, "\n#endif /* OPT_EVAL */\n");
1532 }
1533
1534 /******************************************************************************/
1535 static void
init_statevars(void)1536 init_statevars(void)
1537 {
1538 static const char *const head[] =
1539 {
1540 "",
1541 "/*\tlist of recognized state variables\t*/",
1542 "",
1543 "extern BLIST blist_statevars;",
1544 "",
1545 "#ifdef realdef",
1546 "DECL_EXTERN_CONST(char *const statevars[]) = {"
1547 };
1548 static int done;
1549
1550 if (!done++)
1551 write_lines(nevars, head);
1552 }
1553
1554 #define NonNull(s) ((s) ? (s) : "")
1555 /*
1556 * vec[0] is empty
1557 * vec[1] is variable name
1558 * vec[2] is symbol
1559 * vec[3] is condition
1560 * vec[4] is comment (unused so far)
1561 */
1562 static void
save_statevars(char * type,char ** vec)1563 save_statevars(char *type, char **vec)
1564 {
1565 char *name = vec[1];
1566 char *vars = vec[2];
1567 char *cond = vec[3];
1568 char *key = Vars2Key(type, name, cond);
1569
1570 InsertSorted(&all_statevars, key, vars, "", cond, vec[4], "");
1571 free(key);
1572 }
1573
1574 static void
dump_statevars(void)1575 dump_statevars(void)
1576 {
1577 static const char *const middle[] =
1578 {
1579 "\tNULL\t/* ends table for name-completion */",
1580 "};",
1581 "BLIST blist_statevars = init_blist(statevars);",
1582 "#else",
1583 "extern const char *const statevars[];",
1584 "#endif",
1585 "",
1586 "typedef enum {",
1587 };
1588 static const char *const middle1[] =
1589 {
1590 "\tNum_StateVars",
1591 "} enumStateVars;",
1592 "",
1593 ""
1594 };
1595 static const char *const middle2[] =
1596 {
1597 "",
1598 "typedef int (StateFunc)(TBUFF **resultp, const char *valuep);",
1599 "",
1600 "typedef struct {",
1601 "\tStateFunc *func;",
1602 "\tchar type;",
1603 "#if OPT_ONLINEHELP",
1604 "\tconst char* help;",
1605 "#endif",
1606 "} StateVars;",
1607 "",
1608 "#ifdef realdef",
1609 "",
1610 "#undef DATA",
1611 "#if OPT_ONLINEHELP",
1612 "#define DATA(func,type,help) { func, type, help }",
1613 "#else",
1614 "#define DATA(func,type,help) { func, type}",
1615 "#endif",
1616 "",
1617 "DECL_EXTERN(const StateVars statevar_funcs[]) = {",
1618 ""
1619 };
1620 static const char *const tail[] =
1621 {
1622 "\tDATA( (StateFunc *)NULL, 0, 0 )",
1623 "};",
1624 "#else",
1625 "extern const StateVars statevar_funcs[];",
1626 "#endif /* realdef */",
1627 "",
1628 };
1629 char temp[LEN_BUFFER], norm[LEN_BUFFER], type[LEN_BUFFER];
1630 LIST *p;
1631 char *s;
1632 int first = 1;
1633
1634 BeginIf();
1635 for (p = all_statevars; p != 0; p = p->nst) {
1636 if (sscanf(p->Name, "%s\n%s", norm, type) != 2)
1637 continue;
1638 if (first) {
1639 init_statevars();
1640 first = 0;
1641 }
1642 WriteIf(nevars, p->Cond);
1643 Fprintf(nevars, "\t%s,\n", s = Name2Symbol(norm));
1644 free(s);
1645 }
1646 FlushIf(nevars);
1647 write_lines(nevars, middle);
1648
1649 for (p = all_statevars; p != 0; p = p->nst) {
1650 WriteIf(nevars, p->Cond);
1651 Fprintf(nevars, "\tVAR_%s,\n", p->Func);
1652 }
1653 FlushIf(nevars);
1654
1655 write_lines(nevars, middle1);
1656 /* emit the variable get/set routine prototypes */
1657 for (p = all_statevars; p != 0; p = p->nst) {
1658 WriteIf(nevars, p->Cond);
1659 Fprintf(nevars, "int var_%s(TBUFF **resp, const char *valp);\n",
1660 p->Func);
1661 }
1662 FlushIf(nevars);
1663 write_lines(nevars, middle2);
1664 /* emit the variable get/set routine table */
1665 for (p = all_statevars; p != 0; p = p->nst) {
1666 if (sscanf(p->Name, "%s\n%s", norm, type) != 2)
1667 continue;
1668 WriteIf(nevars, p->Cond);
1669 Sprintf(temp, "\tDATA( var_%s,", p->Func);
1670 (void) PadTo(32, temp);
1671 Sprintf(temp + strlen(temp), "VALTYPE_%s,", c2TYPE(*type));
1672 (void) PadTo(50, temp);
1673 Sprintf(temp + strlen(temp), "\"%s\" ),", p->Note);
1674 Fprintf(nevars, "%s\n", temp);
1675 }
1676 FlushIf(nevars);
1677 write_lines(nevars, tail);
1678 }
1679
1680 /******************************************************************************/
1681 static void
save_fsms(char ** vec)1682 save_fsms(char **vec)
1683 {
1684 InsertSorted(&all_fsms,
1685 lowercase(vec[1]),
1686 "",
1687 vec[2],
1688 vec[3],
1689 vec[0],
1690 "");
1691 }
1692
1693 static void
init_fsms(void)1694 init_fsms(void)
1695 {
1696 int n;
1697
1698 if (fsm_uc_name == 0) {
1699 badfmt("Missing table name");
1700 } else {
1701
1702 for (n = 0; fsm_uc_name[n] != '\0'; n++)
1703 fsm_uc_name[n] = (char) toUpper(fsm_uc_name[n]);
1704 Fprintf(nefsms, "\n");
1705 Fprintf(nefsms, "extern FSM_BLIST fsm_%s_blist;\n\n", fsm_lc_name);
1706 Fprintf(nefsms, "#if OPT_%s_CHOICES\n", fsm_uc_name);
1707 Fprintf(nefsms, "#ifndef realdef\n");
1708 Fprintf(nefsms, "extern const FSM_CHOICES fsm_%s_choices[];\n", fsm_lc_name);
1709 Fprintf(nefsms, "#else\n");
1710 Fprintf(nefsms,
1711 "DECL_EXTERN_CONST(FSM_CHOICES fsm_%s_choices[]) = %c\n",
1712 fsm_lc_name, L_CURL);
1713 }
1714 }
1715
1716 static void
dump_fsms(void)1717 dump_fsms(void)
1718 {
1719 static const char *const middle[] =
1720 {
1721 "\tEND_CHOICES\t/* ends table for name-completion */",
1722 "};",
1723 };
1724 char temp[MAX_BUFFER];
1725 LIST *p;
1726 int count;
1727
1728 if (all_fsms != 0) {
1729 BeginIf();
1730 for (p = all_fsms, count = 0; p != 0; p = p->nst) {
1731 if (!count++)
1732 init_fsms();
1733 WriteIf(nefsms, p->Cond);
1734 Sprintf(temp, "\t{ \"%s\",", p->Name);
1735 Fprintf(nefsms, "%s%s },\n", PadTo(40, temp), p->Data);
1736 }
1737 FlushIf(nefsms);
1738
1739 write_lines(nefsms, middle);
1740
1741 Fprintf(nefsms, "FSM_BLIST fsm_%s_blist = {\n", fsm_lc_name);
1742 Fprintf(nefsms, "\tfsm_%s_choices,\n", fsm_lc_name);
1743 Fprintf(nefsms, "\tinit_blist(fsm_%s_choices)\n", fsm_lc_name);
1744 Fprintf(nefsms, "};\n");
1745
1746 Fprintf(nefsms, "#endif\n");
1747 Fprintf(nefsms, "#endif /* OPT_%s_CHOICES */\n", fsm_lc_name);
1748
1749 free_LIST(&all_fsms);
1750
1751 free(fsm_uc_name);
1752 fsm_uc_name = 0;
1753
1754 free(fsm_lc_name);
1755 fsm_lc_name = 0;
1756 }
1757 }
1758
1759 /******************************************************************************/
1760 static void
start_fsms_h(char ** argv,char * name)1761 start_fsms_h(char **argv, char *name)
1762 {
1763 static const char *const head[] =
1764 {
1765 "#ifndef NEFSMS_H",
1766 "#define NEFSMS_H 1",
1767 };
1768
1769 if (!nefsms) {
1770 nefsms = OpenHeader("nefsms.h", argv);
1771 write_lines(nefsms, head);
1772 }
1773 dump_fsms();
1774 fsm_uc_name = StrAlloc(name);
1775 fsm_lc_name = StrAlloc(name);
1776 }
1777
1778 static void
finish_fsms_h(void)1779 finish_fsms_h(void)
1780 {
1781 if (nefsms)
1782 Fprintf(nefsms, "\n#endif /* NEFSMS_H */\n");
1783 }
1784
1785 /******************************************************************************/
1786 static void
dump_execs(FILE * fp,int count)1787 dump_execs(FILE *fp, int count)
1788 {
1789 int n;
1790
1791 for (n = 1; n <= count; n++) {
1792 Fprintf(fp, "#if OPT_EXEC_MACROS>%d\n", n - 1);
1793 Fprintf(fp, "int\n");
1794 Fprintf(fp, "cbuf%d(int f, int n)\n", n);
1795 Fprintf(fp, "{\n\treturn cbuf(f, n, %d);\n}\n", n);
1796 Fprintf(fp, "#endif\n");
1797 }
1798 fclose(fp);
1799 }
1800
1801 /******************************************************************************/
1802 static void
save_funcs(char * func,char * flags,char * cond,char * old_cond,char * help)1803 save_funcs(
1804 char *func,
1805 char *flags,
1806 char *cond,
1807 char *old_cond,
1808 char *help)
1809 {
1810 char temp[MAX_BUFFER];
1811 char *s;
1812 LIST *p;
1813
1814 if (strcmp(cond, old_cond)) {
1815 if (*old_cond) {
1816 SaveEndif(all_funcs);
1817 SaveEndif(all__FUNCs);
1818 SaveEndif(all__CMDFs);
1819 }
1820 if (*cond) {
1821 Sprintf(temp, "#if %s", cond);
1822 InsertOnEnd(&all_funcs, temp);
1823 InsertOnEnd(&all__FUNCs, temp);
1824 InsertOnEnd(&all__CMDFs, temp);
1825 }
1826 (void) strcpy(old_cond, cond);
1827 }
1828 Sprintf(temp, "extern int %s ( int f, int n );", func);
1829 InsertOnEnd(&all_funcs, temp);
1830
1831 s = strcpy(temp, "\n");
1832
1833 s = append(s, "static const char *syn_");
1834 s = append(s, func);
1835 s = append(s, "[] = \n{\n");
1836 for (p = all_aliases; p != 0; p = p->nst) {
1837 if (p->Cond[0]) {
1838 s = append(s, "#if ");
1839 s = append(s, p->Cond);
1840 s = append(s, "\n");
1841 }
1842 s = append(s, "\t\"");
1843 s = append(s, p->Name);
1844 s = append(s, "\",\n");
1845 if (p->Cond[0]) {
1846 s = append(s, "#endif\n");
1847 }
1848 }
1849 s = append(s, "\t0\n};\n");
1850 s = append(s, "\n");
1851
1852 s = append(s, "DECL_EXTERN_CONST(CMDFUNC f_");
1853 s = append(s, func);
1854 s = append(s, ")");
1855 (void) PadTo(32, temp);
1856 s = append(s, "=\n{\n\tINIT_UNION(");
1857 s = append(s, func);
1858 s = append(s, "),\n\t");
1859 s = append(s, flags);
1860 s = append(s, "\n\t,syn_");
1861 s = append(s, func);
1862 s = append(s, "\n#if OPT_MACRO_ARGS\n\t,0\n#endif");
1863 s = append(s, "\n#if OPT_TRACE\n\t,\"");
1864 s = append(s, func);
1865 s = append(s, "\"\n#endif");
1866 s = append(s, "\n#if OPT_ONLINEHELP\n\t,\"");
1867 s = append(s, help);
1868 (void) append(s, "\"\n#endif\n};");
1869 InsertOnEnd(&all__FUNCs, temp);
1870
1871 s = append(strcpy(temp, "extern const CMDFUNC f_"), func);
1872 (void) append(s, ";");
1873 InsertOnEnd(&all__CMDFs, temp);
1874
1875 free_LIST(&all_aliases);
1876 }
1877
1878 static void
dump_funcs(FILE * fp,LIST * head)1879 dump_funcs(FILE *fp, LIST * head)
1880 {
1881 LIST *p;
1882 for (p = head; p != 0; p = p->nst)
1883 Fprintf(fp, "%s\n", p->Name);
1884 }
1885
1886 /******************************************************************************/
1887 static void
save_gmodes(char * type,char ** vec)1888 save_gmodes(char *type, char **vec)
1889 {
1890 char *key = Mode2Key(type, vec[1], vec[4], FALSE);
1891
1892 InsertSorted(&all_gmodes, key, vec[2], vec[3], vec[4], vec[0], "");
1893 #if NO_LEAKS
1894 free(key);
1895 #endif
1896 }
1897
1898 static void
dump_gmodes(void)1899 dump_gmodes(void)
1900 {
1901 static const char *const top[] =
1902 {
1903 "",
1904 "/* global mode flags\t*/",
1905 "/* the indices of G_VALUES.v[] */",
1906 };
1907 static const char *const middle[] =
1908 {
1909 "",
1910 "typedef struct G_VALUES {",
1911 "\t/* each entry is a val, and a ptr to a val */",
1912 "\tstruct VAL gv[MAX_G_VALUES+1];",
1913 "} G_VALUES;",
1914 "",
1915 "#ifdef realdef",
1916 "DECL_EXTERN_CONST(struct VALNAMES g_valnames[]) = {",
1917 };
1918 static const char *const bottom[] =
1919 {
1920 "",
1921 "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
1922 "};",
1923 "#else",
1924 "extern const struct VALNAMES g_valnames[];",
1925 "#endif",
1926 };
1927
1928 write_lines(nemode, top);
1929 WriteIndexStruct(nemode, all_gmodes, "Globals");
1930 WriteModeDefines(all_gmodes, "Globals");
1931 write_lines(nemode, middle);
1932 WriteModeSymbols(all_gmodes);
1933 write_lines(nemode, bottom);
1934 }
1935
1936 /******************************************************************************/
1937 static void
save_names(char * name,char * func,char * cond,char * flags)1938 save_names(char *name, char *func, char *cond, char *flags)
1939 {
1940 InsertSorted(&all_names, name, func, "", cond, "", flags);
1941 }
1942
1943 static void
save_aliases(char * name,char * func,char * cond,char * flags)1944 save_aliases(char *name, char *func, char *cond, char *flags)
1945 {
1946 InsertSorted(&all_aliases, name, func, "", cond, "", flags);
1947 }
1948
1949 static void
dump_names(void)1950 dump_names(void)
1951 {
1952 LIST *m;
1953 char temp[MAX_BUFFER];
1954
1955 Fprintf(nename, "#include <blist.h>\n");
1956 Fprintf(nename, "\n");
1957 Fprintf(nename, "extern BLIST blist_nametbl;\n");
1958 Fprintf(nename, "extern BLIST blist_glbstbl;\n");
1959 Fprintf(nename, "\n");
1960 Fprintf(nename, "#ifdef real_NAMETBL\n");
1961 Fprintf(nename, "\n");
1962 Fprintf(nename, "EXTERN_CONST NTAB nametbl[] = {\n");
1963
1964 BeginIf();
1965 for (m = all_names; m != NULL; m = m->nst) {
1966 WriteIf(nename, m->Cond);
1967 Sprintf(temp, "\t{ \"%s\",", m->Name);
1968 Fprintf(nename, "%s&f_%s },\n", PadTo(40, temp), m->Func);
1969 }
1970 FlushIf(nename);
1971 Fprintf(nename, "\t{ NULL, NULL }\n};\n");
1972 Fprintf(nename, "\n");
1973 Fprintf(nename, "BLIST blist_nametbl = init_blist(nametbl);\n");
1974 Fprintf(nename, "\n");
1975 Fprintf(nename, "EXTERN_CONST NTAB glbstbl[] = {\n");
1976 BeginIf();
1977 for (m = all_names; m != NULL; m = m->nst) {
1978 if (m->Flag != 0 && strstr(m->Flag, "GLOBOK") != 0) {
1979 WriteIf(nename, m->Cond);
1980 Sprintf(temp, "\t{ \"%s\",", m->Name);
1981 Fprintf(nename, "%s&f_%s },\n", PadTo(40, temp), m->Func);
1982 }
1983 }
1984 FlushIf(nename);
1985 Fprintf(nename, "\t{ NULL, NULL }\n};\n");
1986 Fprintf(nename, "\n");
1987 Fprintf(nename, "BLIST blist_glbstbl = init_blist(glbstbl);\n");
1988 Fprintf(nename, "\n");
1989 Fprintf(nename, "#else\n");
1990 Fprintf(nename, "\n");
1991 Fprintf(nename, "#endif\n");
1992 }
1993
1994 /******************************************************************************/
1995 static void
init_ufuncs(void)1996 init_ufuncs(void)
1997 {
1998 static const char *const head[] =
1999 {
2000 "",
2001 "/*\tlist of recognized macro language functions\t*/",
2002 "",
2003 "typedef enum {",
2004 };
2005 static const char *const middle[] =
2006 {
2007 "} UFuncCode;",
2008 "",
2009 "typedef struct UFUNC {",
2010 "\tconst char *f_name;\t/* name of function */",
2011 "\tunsigned f_code;",
2012 "#if OPT_ONLINEHELP",
2013 "\tconst char *f_help;",
2014 "#endif",
2015 "} UFUNC;",
2016 "",
2017 "#define NARGMASK 0x000f",
2018 "#define NUM 0x0010",
2019 "#define BOOL 0x0020",
2020 "#define STR 0x0040",
2021 "#define NRET 0x0100",
2022 "#define BRET 0x0200",
2023 "#define SRET 0x0400",
2024 "",
2025 "#ifdef realdef",
2026 "",
2027 "#undef DATA",
2028 "#if OPT_ONLINEHELP",
2029 "#define DATA(name,code,help) {name,(unsigned)(code),help}",
2030 "#else",
2031 "#define DATA(name,code,help) {name,(unsigned)(code)}",
2032 "#endif",
2033 "",
2034 "DECL_EXTERN_CONST(UFUNC vl_ufuncs[]) = {",
2035 };
2036 static int done;
2037 LIST *p;
2038 int count;
2039
2040 if (!done++) {
2041 write_lines(nevars, head);
2042 for (p = all_ufuncs, count = 0; p != 0; p = p->nst) {
2043 if (!count++)
2044 Fprintf(nevars, "\t UF%s = 0\n", p->Func);
2045 else
2046 Fprintf(nevars, "\t,UF%s\n", p->Func);
2047 }
2048 Fprintf(nevars, "\n\t,NFUNCS /* %d */\n", count);
2049 write_lines(nevars, middle);
2050 }
2051 }
2052
2053 static void
save_ufuncs(char ** vec)2054 save_ufuncs(char **vec)
2055 {
2056 InsertSorted(&all_ufuncs, vec[1], vec[2], vec[3], "", vec[4], "");
2057 }
2058
2059 static void
dump_ufuncs(void)2060 dump_ufuncs(void)
2061 {
2062 static const char *const head[] =
2063 {
2064 "extern BLIST blist_ufuncs;",
2065 "",
2066 };
2067 static const char *const middle[] =
2068 {
2069 "\tDATA(NULL, 0, \"\"),",
2070 "};",
2071 "#undef DATA",
2072 "BLIST blist_ufuncs = init_blist(vl_ufuncs);",
2073 "#else",
2074 "extern const UFUNC vl_ufuncs[];",
2075 "#endif",
2076 "",
2077 };
2078 char temp[MAX_BUFFER];
2079 LIST *p;
2080 int count;
2081
2082 write_lines(nevars, head);
2083 for (p = all_ufuncs, count = 0; p != 0; p = p->nst) {
2084 if (!count++)
2085 init_ufuncs();
2086 Sprintf(temp, "\tDATA(\"%s\",", p->Name);
2087 (void) PadTo(32, temp);
2088 Sprintf(temp + strlen(temp), "%s,", p->Data);
2089 (void) PadTo(48, temp);
2090 Sprintf(temp + strlen(temp), "\"%s\"),", p->Note);
2091 Fprintf(nevars, "%s\n", temp);
2092 }
2093 write_lines(nevars, middle);
2094 }
2095
2096 /******************************************************************************/
2097 static void
save_wmodes(char * type,char ** vec)2098 save_wmodes(char *type, char **vec)
2099 {
2100 char *key = Mode2Key(type, vec[1], vec[4], FALSE);
2101 InsertSorted(&all_wmodes, key, vec[2], vec[3], vec[4], vec[0], "");
2102 #if NO_LEAKS
2103 free(key);
2104 #endif
2105 }
2106
2107 static void
dump_wmodes(void)2108 dump_wmodes(void)
2109 {
2110 static const char *top[] =
2111 {
2112 "",
2113 "/* these are the boolean, integer, and pointer value'd settings that are",
2114 " * associated with a window, and usually settable by a user. There",
2115 " * is a global set that is inherited into a buffer, and its windows",
2116 " * in turn are inherit the buffer's set.",
2117 " */",
2118 };
2119 static const char *middle[] =
2120 {
2121 "",
2122 "typedef struct W_VALUES {",
2123 "\t/* each entry is a val, and a ptr to a val */",
2124 "\tstruct VAL wv[MAX_W_VALUES+1];",
2125 "} W_VALUES;",
2126 "",
2127 "#ifdef realdef",
2128 "DECL_EXTERN_CONST(struct VALNAMES w_valnames[]) = {",
2129 };
2130 static const char *bottom[] =
2131 {
2132 "",
2133 "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
2134 "};",
2135 "#else",
2136 "extern const struct VALNAMES w_valnames[];",
2137 "#endif",
2138 };
2139
2140 write_lines(nemode, top);
2141 WriteIndexStruct(nemode, all_wmodes, "Windows");
2142 WriteModeDefines(all_wmodes, "Windows");
2143 write_lines(nemode, middle);
2144 WriteModeSymbols(all_wmodes);
2145 write_lines(nemode, bottom);
2146 }
2147
2148 /* The accepted format for a Win32 special key binding is:
2149 *
2150 * {<modifier>+}...<key>
2151 *
2152 * where:
2153 *
2154 * <modifier> := SHIFT | CTRL | ALT
2155 *
2156 * <key> := Insert | 6
2157 *
2158 * See the comments at the end of the file "cmdtbl" for a complete
2159 * explanation of why more <key>'s are not supported.
2160 *
2161 * Caution
2162 * -------
2163 * The error checking supplied in mkw32binding() and InsertSorted() can
2164 * be fooled.
2165 */
2166 #ifdef _WIN32
2167 static void
mkw32binding(char * key,char * conditional,char * func,char * fcond)2168 mkw32binding(char *key, char *conditional, char *func, char *fcond)
2169 {
2170 #define KEYTOKEN "mod_KEY"
2171
2172 char *cp = key, *match, *tmp, *defp, cum_defn[512];
2173 int nomore_keys, saw_modifier;
2174
2175 strcpy(cum_defn, KEYTOKEN);
2176 defp = cum_defn + sizeof(KEYTOKEN) - 1;
2177 saw_modifier = 0;
2178 while (*cp) {
2179 nomore_keys = 1; /* An assumption. */
2180 if ((tmp = strchr(cp, '+')) != NULL)
2181 *tmp = '\0';
2182 match = NULL;
2183 if (stricmp(cp, "shift") == 0) {
2184 match = "mod_SHIFT";
2185 nomore_keys = 0; /* Okay to stack modifiers */
2186 saw_modifier = 1;
2187 } else if (stricmp(cp, "alt") == 0) {
2188 match = "mod_ALT";
2189 nomore_keys = 0; /* Okay to stack modifiers */
2190 saw_modifier = 1;
2191 } else if (stricmp(cp, "ctrl") == 0) {
2192 match = "mod_CTRL";
2193 nomore_keys = 0; /* Okay to stack modifiers */
2194 saw_modifier = 1;
2195 } else if (stricmp(cp, "insert") == 0)
2196 match = "KEY_Insert";
2197 else if (stricmp(cp, "delete") == 0)
2198 match = "KEY_Delete";
2199 if (match) {
2200 defp += sprintf(defp, "|%s", match);
2201 if (!tmp)
2202 break;
2203 cp = tmp + 1;
2204 } else if (*cp == '6')
2205 defp += sprintf(defp, "|'%c'", *cp++);
2206 if (*cp && nomore_keys)
2207 badfmt("invalid/unsupported Win32 key sequence");
2208 }
2209 if (!saw_modifier)
2210 badfmt("missing Win32 key modifier");
2211 InsertSorted(&all_w32bind,
2212 cum_defn,
2213 func,
2214 "",
2215 formcond(fcond, conditional),
2216 "",
2217 "");
2218 #undef KEYTOKEN
2219 }
2220 #else /* Not a Win32 host -> dummy function -- doesn't do a thing */
2221 #define mkw32binding(key, conditional, func, fcond) /*EMPTY */
2222 #endif /* _WIN32 */
2223
2224 /******************************************************************************/
2225 #if NO_LEAKS
2226 /*
2227 * Free all memory allocated within 'mktbls'. This is used both for debugging
2228 * as well as for allowing 'mktbls' to be an application procedure that is
2229 * repeatedly invoked from a GUI.
2230 */
2231 static void
free_mktbls(void)2232 free_mktbls(void)
2233 {
2234 int k;
2235
2236 free_LIST(&all_names);
2237 free_LIST(&all_aliases);
2238 free_LIST(&all_funcs);
2239 free_LIST(&all__FUNCs);
2240 free_LIST(&all__CMDFs);
2241 free_LIST(&all_statevars);
2242 free_LIST(&all_ufuncs);
2243 free_LIST(&all_modes);
2244 free_LIST(&all_submodes);
2245 free_LIST(&all_kbind);
2246 free_LIST(&all_w32bind);
2247 free_LIST(&all_gmodes);
2248 free_LIST(&all_mmodes);
2249 free_LIST(&all_qmodes);
2250 free_LIST(&all_bmodes);
2251 free_LIST(&all_wmodes);
2252
2253 for (k = 0; k < LEN_CHRSET; k++) {
2254 FreeIfNeeded(bindings[k]);
2255 FreeIfNeeded(conditions[k]);
2256 }
2257 #if DOALLOC
2258 show_alloc();
2259 #endif
2260 }
2261 #else
2262 #define free_mktbls()
2263 #endif /* NO_LEAKS */
2264
2265 /*
2266 * Fix for quoted octal codes, which are sign-extended if the value is above
2267 * \177, e.g., vile's KEY_F21 to KEY_F35.
2268 */
2269 static char *
ok_char(char * src)2270 ok_char(char *src)
2271 {
2272 static char temp[20];
2273
2274 if (src[0] != '\\' || src[1] == '\\') {
2275 Sprintf(temp, "'%s'", src);
2276 } else {
2277 strncpy(temp, src, sizeof(temp) - 1);
2278 *temp = '0';
2279 }
2280 return temp;
2281 }
2282
2283 /******************************************************************************/
2284 int
main(int argc,char * argv[])2285 main(int argc, char *argv[])
2286 {
2287 char *vec[MAX_PARSE];
2288 char line[MAX_BUFFER];
2289 char func[LEN_BUFFER];
2290 char flags[LEN_BUFFER];
2291 char funchelp[MAX_BUFFER];
2292 char old_fcond[LEN_BUFFER];
2293 char fcond[LEN_BUFFER];
2294 char modetype[LEN_BUFFER];
2295 SECTIONS section;
2296 int r;
2297
2298 func[0] = flags[0] = fcond[0] = old_fcond[0] = modetype[0] = EOS;
2299
2300 if (setjmp(my_top))
2301 return (BADEXIT);
2302
2303 if (argc != 2) {
2304 Fprintf(stderr, "usage: mktbls cmd-file\n");
2305 longjmp(my_top, 1);
2306 }
2307
2308 if ((cmdtbl = fopen(inputfile = argv[1], "r")) == NULL) {
2309 Fprintf(stderr, "mktbls: couldn't open cmd-file\n");
2310 longjmp(my_top, 1);
2311 }
2312
2313 *old_fcond = EOS;
2314 section = SECT_CMDS;
2315
2316 /* process each input line */
2317 while (fgets(line, sizeof(line), cmdtbl) != NULL) {
2318 char col0 = line[0], col1 = line[1];
2319
2320 l++;
2321 r = Parse(line, vec);
2322
2323 switch (col0) {
2324 case '#': /* comment */
2325 case '\n': /* empty-list */
2326 break;
2327
2328 case '.': /* a new section */
2329 switch (col1) {
2330 case 'a':
2331 section = SECT_ABBR;
2332 break;
2333 case 'c':
2334 section = SECT_CMDS;
2335 break;
2336 case 'e':
2337 section = SECT_VARS;
2338 start_vars_h(argv);
2339 break;
2340 case 'f':
2341 section = SECT_FUNC;
2342 start_vars_h(argv);
2343 break;
2344 case 'g':
2345 section = SECT_GBLS;
2346 break;
2347 case 'm':
2348 section = SECT_MAJR;
2349 predefine_submodes(vec, r);
2350 break;
2351 case 'q':
2352 section = SECT_QUAL;
2353 break;
2354 case 'b':
2355 section = SECT_BUFF;
2356 break;
2357 case 't':
2358 section = SECT_FSMS;
2359 start_fsms_h(argv, vec[2]);
2360 break;
2361 case 'w':
2362 section = SECT_WIND;
2363 break;
2364 default:
2365 badfmt("unknown section");
2366 }
2367 break;
2368
2369 case '\t': /* a new function */
2370 switch (section) {
2371 case SECT_ABBR:
2372 if (r != 2)
2373 badfmt("looking for ABBR assignments");
2374 save_abbrs(vec);
2375 break;
2376 case SECT_CMDS:
2377 switch (col1) {
2378 case '"': /* then it's an english name */
2379 if (r < 1 || r > 2)
2380 badfmt("looking for english name");
2381
2382 save_names(vec[1], func, formcond(fcond, vec[2]), flags);
2383 save_aliases(vec[1], func, formcond(fcond, vec[2]), flags);
2384 break;
2385
2386 case '\'': /* then it's a key */
2387 if (r < 1 || r > 3)
2388 badfmt("looking for key binding");
2389
2390 if (strcmp("W32KY", vec[2]) == 0) {
2391 mkw32binding(vec[1], vec[3], func, fcond);
2392 } else {
2393 if (strncmp("KEY_", vec[2], (size_t) 4) == 0) {
2394 if (strncmp("FN-", vec[1], (size_t) 3) != 0)
2395 badfmt("KEY_xxx definition must for FN- binding");
2396 if (!nefkeys)
2397 nefkeys = OpenHeader("nefkeys.h", argv);
2398 Fprintf(nefkeys, "#define %16s (SPEC|%s)\n",
2399 vec[2], ok_char(vec[1] + 3));
2400 vec[2] = vec[3];
2401 }
2402 save_bindings(vec[1], func, formcond(fcond, vec[2]));
2403 }
2404 break;
2405
2406 case '<': /* then it's a help string */
2407 /* put code here. */
2408 (void) my_strncpy(funchelp, vec[1], sizeof(funchelp));
2409 break;
2410
2411 default:
2412 badfmt("bad line");
2413 }
2414 break;
2415
2416 case SECT_GBLS:
2417 if (r < 2 || r > 4)
2418 badfmt("looking for GLOBAL modes");
2419 save_gmodes(modetype, vec);
2420 break;
2421
2422 case SECT_MAJR:
2423 if (r < 2 || r > 4)
2424 badfmt("looking for MAJOR modes");
2425 save_mmodes(modetype, vec);
2426 break;
2427
2428 case SECT_QUAL:
2429 if (r < 2 || r > 4)
2430 badfmt("looking for QUALIFIER modes");
2431 save_qmodes(modetype, vec);
2432 break;
2433
2434 case SECT_BUFF:
2435 if (r < 2 || r > 4)
2436 badfmt("looking for BUFFER modes");
2437 save_bmodes(modetype, vec);
2438 break;
2439
2440 case SECT_WIND:
2441 if (r < 2 || r > 4)
2442 badfmt("looking for WINDOW modes");
2443 save_wmodes(modetype, vec);
2444 break;
2445
2446 case SECT_VARS:
2447 if (r < 2 || r > 4)
2448 badfmt("looking for state variables");
2449 save_statevars(modetype, vec);
2450 break;
2451
2452 default:
2453 badfmt("did not expect a tab");
2454 }
2455 break;
2456
2457 default: /* cache information about funcs */
2458 switch (section) {
2459 case SECT_CMDS:
2460 if (r < 2 || r > 3)
2461 badfmt("looking for new function");
2462
2463 /* don't save this yet -- we may get a
2464 a help line for it. save the previous
2465 one now, and hang onto this one */
2466 if (func[0]) { /* flush the old one */
2467 save_funcs(func, flags, fcond, old_fcond, funchelp);
2468 funchelp[0] = EOS;
2469 }
2470 (void) my_strncpy(func, vec[1], sizeof(func));
2471 (void) my_strncpy(flags, vec[2], sizeof(flags));
2472 (void) my_strncpy(fcond, vec[3], sizeof(fcond));
2473 break;
2474
2475 case SECT_FSMS:
2476 save_fsms(vec);
2477 break;
2478
2479 case SECT_VARS:
2480 if (r != 1
2481 || (!strcmp(vec[1], "bool")
2482 && !strcmp(vec[1], "enum")
2483 && !strcmp(vec[1], "int")
2484 && !strcmp(vec[1], "string")
2485 && !strcmp(vec[1], "regex")))
2486 badfmt("looking for mode datatype");
2487 (void) my_strncpy(modetype, vec[1], sizeof(modetype));
2488 break;
2489
2490 case SECT_FUNC:
2491 if (r < 2 || r > 4)
2492 badfmt("looking for UFUNC func[]");
2493 save_ufuncs(vec);
2494 break;
2495
2496 case SECT_GBLS:
2497 case SECT_MAJR:
2498 case SECT_QUAL:
2499 case SECT_BUFF:
2500 case SECT_WIND:
2501 if (r != 1
2502 || (strcmp(vec[1], "bool")
2503 && strcmp(vec[1], "enum")
2504 && strcmp(vec[1], "int")
2505 && strcmp(vec[1], "string")
2506 && strcmp(vec[1], "regex")))
2507 badfmt("looking for mode datatype");
2508 (void) my_strncpy(modetype, vec[1], sizeof(modetype));
2509 break;
2510
2511 default:
2512 badfmt("section not implemented");
2513 }
2514 }
2515 }
2516 fclose(cmdtbl);
2517
2518 if (func[0]) { /* flush the old one */
2519 save_funcs(func, flags, fcond, old_fcond, funchelp);
2520 funchelp[0] = EOS;
2521 }
2522 if (*old_fcond) {
2523 SaveEndif(all_funcs);
2524 SaveEndif(all__FUNCs);
2525 SaveEndif(all__CMDFs);
2526 }
2527
2528 if (all_names) {
2529 nebind = OpenHeader("nebind.h", argv);
2530 neexec = OpenHeader("neexec.h", argv);
2531 nefunc = OpenHeader("nefunc.h", argv);
2532 neprot = OpenHeader("neproto.h", argv);
2533 nename = OpenHeader("nename.h", argv);
2534 dump_names();
2535 dump_bindings();
2536 dump_execs(neexec, OPT_EXEC_MACROS);
2537 dump_funcs(neprot, all_funcs);
2538
2539 Fprintf(nefunc, "\n#ifdef real_CMDFUNCS\n\n");
2540 dump_funcs(nefunc, all__FUNCs);
2541 Fprintf(nefunc, "\n#else\n\n");
2542 dump_funcs(nefunc, all__CMDFs);
2543 Fprintf(nefunc, "\n#endif\n");
2544 }
2545
2546 if (all_statevars) {
2547 dump_statevars();
2548 dump_ufuncs();
2549 finish_vars_h();
2550 }
2551
2552 dump_fsms();
2553 finish_fsms_h();
2554
2555 if (all_wmodes || all_bmodes) {
2556 nemode = OpenHeader("nemode.h", argv);
2557 dump_majors();
2558 dump_all_modes();
2559 dump_all_submodes();
2560 dump_gmodes();
2561 dump_mmodes();
2562 dump_qmodes();
2563 dump_bmodes();
2564 dump_wmodes();
2565 }
2566
2567 if (nebind != 0)
2568 fclose(nebind);
2569 if (nefkeys != 0)
2570 fclose(nefkeys);
2571 if (nefsms != 0)
2572 fclose(nefsms);
2573 if (nefunc != 0)
2574 fclose(nefunc);
2575 if (nemode != 0)
2576 fclose(nemode);
2577 if (nename != 0)
2578 fclose(nename);
2579 if (neprot != 0)
2580 fclose(neprot);
2581 if (nevars != 0)
2582 fclose(nevars);
2583
2584 free_mktbls();
2585 return (GOODEXIT);
2586 }
2587