home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / vile-src.zip / vile-8.1 / mktbls.c < prev    next >
C/C++ Source or Header  |  1998-07-26  |  48KB  |  2,154 lines

  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) 1990, 1995 by Paul Fox and Tom 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.  * $Header: /usr/build/vile/vile/RCS/mktbls.c,v 1.90 1998/07/26 23:16:21 tom Exp $
  19.  *
  20.  */
  21.  
  22. #define    OPT_IFDEF_MODES    1    /* true iff we can ifdef modes */
  23.  
  24. /* stuff borrowed/adapted from estruct.h */
  25.  
  26. #ifdef HAVE_CONFIG_H
  27. #include "config.h"
  28. #undef DOALLOC    /* since we're not linking with trace.c */
  29. #else    /* !defined(HAVE_CONFIG_H) */
  30.  
  31. #ifndef SYS_VMS
  32. #define SYS_VMS 0
  33. #endif
  34.  
  35. /* Note: VAX-C doesn't recognize continuation-line in ifdef lines */
  36. # ifdef vms
  37. #  define HAVE_STDLIB_H 1
  38. # endif
  39.  
  40.     /* pc-stuff */
  41. # if defined(__TURBOC__) || defined(__WATCOMC__) || defined(__GO32__) || defined(__IBMC__)
  42. #  define HAVE_STDLIB_H 1
  43. # endif
  44.  
  45.     /* unix-stuff */
  46. # if (defined(__GNUC__) && (defined(apollo) || defined(sun) || defined(__hpux) || defined(linux)))
  47. #  define HAVE_STDLIB_H 1
  48. # endif
  49. #endif    /* !defined(HAVE_CONFIG_H) */
  50.  
  51. #ifndef HAVE_STDLIB_H
  52. # define HAVE_STDLIB_H 0
  53. #endif
  54.  
  55. #if HAVE_STDLIB_H
  56. #include <stdlib.h>
  57. #else
  58. # if !defined(HAVE_CONFIG_H) || MISSING_EXTERN_MALLOC
  59. extern    char *    malloc    ( unsigned int len );
  60. # endif
  61. # if !defined(HAVE_CONFIG_H) || MISSING_EXTERN_FREE
  62. extern    void    free    ( char *ptr );
  63. # endif
  64. #endif
  65.  
  66. /*----------------------------------------------------------------------------*/
  67. #ifdef    main    /* we're trying to intercept it, e.g., for Windows wrapper */
  68. #define    ReturnFromMain return
  69. #endif
  70.  
  71. #ifndef    ReturnFromMain
  72. #define ReturnFromMain exit
  73. #endif
  74.  
  75. /*----------------------------------------------------------------------------*/
  76. #ifndef DOALLOC
  77. #define DOALLOC 0
  78. #endif
  79.  
  80. #if DOALLOC
  81. #include "trace.h"
  82. #endif
  83.  
  84. #ifndef NO_LEAKS
  85. #define NO_LEAKS 0
  86. #endif
  87.  
  88. #include <stdio.h>
  89. #include <string.h>
  90. #include <setjmp.h>
  91.  
  92. /* argument for 'exit()' or '_exit()' */
  93. #if    SYS_VMS
  94. #include    <stsdef.h>
  95. #define GOODEXIT    (STS$M_INHIB_MSG | STS$K_SUCCESS)
  96. #define BADEXIT        (STS$M_INHIB_MSG | STS$K_ERROR)
  97. #else
  98. #define GOODEXIT    0
  99. #define BADEXIT        1
  100. #endif
  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    60    /* nominal buffer-length */
  113. #define    MAX_BUFFER    (LEN_BUFFER*10)
  114. #define    LEN_CHRSET    256    /* total # of chars in set (ascii) */
  115.  
  116.     /* patch: why not use <ctype.h> ? */
  117. #define    DIFCNTRL    0x40
  118. #define tocntrl(c)    ((c)^DIFCNTRL)
  119. #define toalpha(c)    ((c)^DIFCNTRL)
  120. #define    DIFCASE        0x20
  121. #define    isUpper(c)    ((c) >= 'A' && (c) <= 'Z')
  122. #define    isLower(c)    ((c) >= 'a' && (c) <= 'z')
  123. #define toUpper(c)    ((c)^DIFCASE)
  124. #define toLower(c)    ((c)^DIFCASE)
  125. #define isboolean(c)    ((c) == 'b' || (c) == 'M')
  126.  
  127. #ifndef    TRUE
  128. #define    TRUE    (1)
  129. #define    FALSE    (0)
  130. #endif
  131.  
  132. #define EOS     '\0'
  133.  
  134. #define    L_CURL    '{'
  135. #define    R_CURL    '}'
  136.  
  137. #define    Fprintf    (void)fprintf
  138. #define    Sprintf    (void)sprintf
  139.  
  140. #if MISSING_EXTERN_FPRINTF
  141. extern    int    fprintf    ( FILE *fp, const char *fmt, ... );
  142. #endif
  143.  
  144. #define    SaveEndif(head)    InsertOnEnd(&head, "#endif")
  145.  
  146. #define    FreeIfNeeded(p) if (p != 0) { free(p); p = 0; }
  147.  
  148. /*--------------------------------------------------------------------------*/
  149.  
  150. typedef    struct stringl {
  151.     char *Name;    /* stores primary-data */
  152.     char *Func;    /* stores secondary-data */
  153.     char *Data;    /* associated data, if any */
  154.     char *Cond;    /* stores ifdef-flags */
  155.     char *Note;    /* stores comment, if any */
  156.     struct stringl *nst;
  157. } LIST;
  158.  
  159. static    char    *Blank = "";
  160.  
  161. static    LIST    *all_names,
  162.         *all_kbind,    /* data for kbindtbl[] */
  163.         *all_w32bind,    /* w32 data for kbindtbl[] */
  164.         *all_funcs,    /* data for extern-lines in neproto.h */
  165.         *all__FUNCs,    /* data for {}-lines in nefunc.h */
  166.         *all__CMDFs,    /* data for extern-lines in nefunc.h */
  167.         *all_envars,
  168.         *all_ufuncs,
  169.         *all_fsms,    /* FSM tables */
  170.         *all_majors,    /* list of predefined major modes */
  171.         *all_modes,    /* data for name-completion of modes */
  172.         *all_submodes,    /* data for name-completion of submodes */
  173.         *all_gmodes,    /* data for GLOBAL modes */
  174.         *all_mmodes,    /* data for MAJOR modes */
  175.         *all_bmodes,    /* data for BUFFER modes */
  176.         *all_wmodes;    /* data for WINDOW modes */
  177.  
  178.     int    main ( int argc, char **argv );
  179.  
  180. static    void    badfmt (const char *s);
  181. static    void    FlushIf (FILE *fp);
  182. static    void    save_all_modes (const char *type, char *normal, const char *abbrev, char *cond);
  183. static    void    save_all_submodes (const char *type, char *normal, const char *abbrev, char *cond);
  184. static    void    free_LIST (LIST **p);
  185.  
  186.     /* definitions for sections of cmdtbl */
  187. #define    SECT_CMDS 0
  188. #define    SECT_FUNC 1
  189. #define    SECT_VARS 2
  190. #define    SECT_GBLS 3
  191. #define    SECT_MAJR 4
  192. #define    SECT_BUFF 5
  193. #define    SECT_WIND 6
  194. #define    SECT_FSMS 7
  195.  
  196.     /* definitions for indices to 'asciitbl[]' vs 'kbindtbl[]' */
  197. #define ASCIIBIND 0
  198. #define CTLXBIND 1
  199. #define CTLABIND 2
  200. #define SPECBIND 3
  201.  
  202. static    char *bindings  [LEN_CHRSET];
  203. static    char *conditions[LEN_CHRSET];
  204. static    const char *tblname   [MAX_BIND] = {"asciitbl", "ctlxtbl", "metatbl", "spectbl" };
  205. static    const char *prefname  [MAX_BIND] = {"",         "CTLX|",   "CTLA|",   "SPEC|" };
  206.  
  207. static    char *fsm_name;
  208. static    char *inputfile;
  209. static    int l = 0;
  210. static    FILE *cmdtbl;
  211. static    FILE *nebind, *neexec, *neprot, *nefunc, *nename;
  212. static    FILE *nevars, *nemode, *nefkeys, *nefsms;
  213. static    jmp_buf my_top;
  214.  
  215. /******************************************************************************/
  216. static int
  217. isSpace(int c)
  218. {
  219.     return c == ' ' || c == '\t' || c == '\n';
  220. }
  221.  
  222. static int
  223. isPrint(int c)
  224. {
  225.     return c >= ' ' && c < 0x7f;
  226. }
  227.  
  228. /******************************************************************************/
  229. static char *
  230. Alloc(unsigned len)
  231. {
  232.     char    *pointer = (char *)malloc(len);
  233.     if (pointer == 0)
  234.         badfmt("bug: not enough memory");
  235.     return pointer;
  236. }
  237.  
  238. static char *
  239. StrAlloc(const char *s)
  240. {
  241.     return strcpy(Alloc((unsigned)strlen(s)+1), s);
  242. }
  243.  
  244. static LIST *
  245. ListAlloc(void)
  246. {
  247.     return (LIST *)Alloc(sizeof(LIST));
  248. }
  249.  
  250. /******************************************************************************/
  251. static void
  252. badfmt(const char *s)
  253. {
  254.     Fprintf(stderr,"\"%s\", line %d: bad format:", inputfile, l);
  255.     Fprintf(stderr,"\t%s\n",s);
  256.     longjmp(my_top,1);
  257. }
  258.  
  259. static void
  260. badfmt2(const char *s, int col)
  261. {
  262.     char    temp[MAX_BUFFER];
  263.     Sprintf(temp, "%s (column %d)", s, col);
  264.     badfmt(temp);
  265. }
  266.  
  267. /******************************************************************************/
  268. static void
  269. WriteLines(
  270. FILE    *fp,
  271. const char *const *list,
  272. int    count)
  273. {
  274.     while (count-- > 0)
  275.         Fprintf(fp, "%s\n", *list++);
  276. }
  277. #define    write_lines(fp,list) WriteLines(fp, list, (int)TABLESIZE(list))
  278.  
  279. /******************************************************************************/
  280. static FILE *
  281. OpenHeader(
  282. const char *name,
  283. char    **argv)
  284. {
  285.     register FILE *fp;
  286.     static const char *progcreat =
  287. "/* %s: this header file was produced automatically by\n\
  288.  * the %s program, based on input from the file %s\n */\n";
  289.  
  290.     if ((fp = fopen(name, "w")) == 0) {
  291.         Fprintf(stderr,"mktbls: couldn't open header file %s\n", name);
  292.         longjmp(my_top,1);
  293.     }
  294.     Fprintf(fp, progcreat, name, argv[0], argv[1]);
  295.     return fp;
  296. }
  297.  
  298. /******************************************************************************/
  299. static void
  300. InsertSorted(
  301. LIST    **headp,
  302. const char *name,
  303. const char *func,
  304. const char *data,
  305. const char *cond,
  306. const char *note)
  307. {
  308.     register LIST *n, *p, *q;
  309.     register int  r;
  310.  
  311.     n = ListAlloc();
  312.     n->Name = StrAlloc(name);
  313.     n->Func = StrAlloc(func);
  314.     n->Data = StrAlloc(data);
  315.     n->Cond = StrAlloc(cond);
  316.     n->Note = StrAlloc(note);
  317.  
  318.     for (p = *headp, q = 0; p != 0; q = p, p = p->nst) {
  319.         if ((r = strcmp(n->Name, p->Name)) < 0)
  320.             break;
  321.         else if (r == 0 && !strcmp(n->Cond, p->Cond))
  322.         {
  323.             printf("name=%s\n", n->Name);    /* FIXME */
  324.             badfmt("duplicate name");
  325.         }
  326.     }
  327.     n->nst = p;
  328.     if (q == 0)
  329.         *headp = n;
  330.     else
  331.         q->nst = n;
  332. }
  333.  
  334. static void
  335. InsertOnEnd(
  336. LIST    **headp,
  337. const char *name)
  338. {
  339.     register LIST *n, *p, *q;
  340.  
  341.     n = ListAlloc();
  342.     n->Name = StrAlloc(name);
  343.     n->Func = Blank;
  344.     n->Data = Blank;
  345.     n->Cond = Blank;
  346.     n->Note = Blank;
  347.  
  348.     for (p = *headp, q = 0; p != 0; q = p, p = p->nst)
  349.         ;
  350.  
  351.     n->nst = 0;
  352.     if (q == 0)
  353.         *headp = n;
  354.     else
  355.         q->nst = n;
  356. }
  357.  
  358. /******************************************************************************/
  359. static char *
  360. append(
  361. char    *dst,
  362. const char *src)
  363. {
  364.     (void)strcat(dst, src);
  365.     return (dst + strlen(dst));
  366. }
  367.  
  368. static char *
  369. formcond(const char *c1, const char *c2)
  370. {
  371.     static char cond[MAX_BUFFER];
  372.     if (c1[0] && c2[0])
  373.         Sprintf(cond, "(%s) & (%s)", c1, c2);
  374.     else if (c1[0] || c2[0])
  375.         Sprintf(cond, "(%s%s)", c1, c2);
  376.     else
  377.         cond[0] = EOS;
  378.     return cond;
  379. }
  380.  
  381. static int
  382. LastCol(char *buffer)
  383. {
  384.     register int    col = 0,
  385.             c;
  386.     while ((c = *buffer++) != 0) {
  387.         if (isPrint(c))
  388.             col++;
  389.         else if (c == '\t')
  390.             col = (col | 7) + 1;
  391.     }
  392.     return col;
  393. }
  394.  
  395. static char *
  396. PadTo(int col, char *buffer)
  397. {
  398.     int    any    = 0,
  399.         len    = strlen(buffer),
  400.         now;
  401.     char    with;
  402.  
  403.     for (;;) {
  404.         if ((now = LastCol(buffer)) >= col) {
  405.             if (any)
  406.                 break;
  407.             else
  408.                 with = ' ';
  409.         } else if (col-now > 1)
  410.             with = '\t';
  411.         else
  412.             with = ' ';
  413.  
  414.         buffer[len++] = with;
  415.         buffer[len]   = EOS;
  416.         any++;
  417.     }
  418.     return buffer;
  419. }
  420.  
  421. static int
  422. two_conds(int c, char *cond)
  423. {
  424.     /* return true if both bindings have different
  425.      conditions associated with them */
  426.     return (cond[0] != '\0' &&
  427.         conditions[c] != NULL &&
  428.         strcmp(cond, conditions[c]) != '\0');
  429. }
  430.  
  431. static void
  432. set_binding (
  433. int    btype,
  434. int    c,
  435. char *    cond,
  436. char *    func)
  437. {
  438.     char    name[MAX_BUFFER];
  439.  
  440.     if (btype != ASCIIBIND) {
  441.         if (c < ' ') {
  442.             Sprintf(name, "%stocntrl('%c')",
  443.                 prefname[btype],
  444.                 toalpha(c));
  445.         } else if (c >= 0x80) {
  446.             Sprintf(name, "%s0x%x",
  447.                 prefname[btype], c);
  448.         } else {
  449.             Sprintf(name, "%s'%s%c'",
  450.                 prefname[btype],
  451.                 (c == '\'' || c == '\\') ? "\\" : "",
  452.                 c);
  453.         }
  454.         InsertSorted(&all_kbind, name, func, "", cond, "");
  455.     } else {
  456.         if (bindings[c] != NULL) {
  457.             if (!two_conds(c,cond))
  458.                 badfmt("duplicate key binding");
  459.             free(bindings[c]);
  460.         }
  461.         bindings[c] = StrAlloc(func);
  462.         if (cond[0]) {
  463.             FreeIfNeeded(conditions[c]);
  464.             conditions[c] = StrAlloc(cond);
  465.         } else {
  466.             conditions[c] = NULL;
  467.         }
  468.     }
  469. }
  470.  
  471. /******************************************************************************/
  472.     /* returns the number of non-comment tokens parsed, with a list of
  473.      * tokens (0=comment) as a side-effect.  Note that quotes are removed
  474.      * from the token, so we have to have them only in the first token! */
  475. static int
  476. Parse(
  477. char    *input,
  478. char    **vec)
  479. {
  480.     register int    expecting = TRUE,
  481.             count = 0,
  482.             quote = 0,
  483.             n,
  484.             c;
  485.  
  486.     for (c = 0; c < MAX_PARSE; c++)
  487.         vec[c] = "";
  488.     for (c = strlen(input); c > 0 && isSpace(input[c-1]); c--)
  489.         input[c-1] = EOS;
  490.  
  491.     for (n = 0; (c = input[n++]) != EOS; ) {
  492.         if (quote) {
  493.             if (c == quote) {
  494.                 quote = 0;
  495.                 if (input[n] && !isSpace(input[n]))
  496.                     badfmt2("expected blank", n);
  497.                 input[n-1] = EOS;
  498.             }
  499.         } else {
  500.             if ((c == '"') || (c == '\'')) {
  501.                 quote = c;
  502.             } else if (c == '<') {
  503.                 c = quote = '>';
  504.             } else if (isSpace(c)) {
  505.                 input[n-1] = EOS;
  506.                 expecting = TRUE;
  507.             } else if (c == '#') {
  508.                 while (isSpace(input[n]))
  509.                     n++;
  510.                 vec[0] = input+n;
  511.                 break;
  512.             }
  513.             if (expecting && !isSpace(c)) {
  514.                 if (count+1 >= MAX_PARSE)
  515.                     break;
  516.                 vec[++count] = input + n - ((c != quote)?1:0);
  517.                 expecting = FALSE;
  518.             }
  519.         }
  520.     }
  521.     return count;
  522. }
  523.  
  524. /******************************************************************************/
  525. static const char *lastIfdef;
  526.  
  527. static void
  528. BeginIf(void)
  529. {
  530.     lastIfdef = 0;
  531. }
  532.  
  533. static void
  534. WriteIf(
  535. FILE    *fp,
  536. const char *cond)
  537. {
  538.     if (cond == 0)
  539.         cond = "";
  540.     if (cond[0] != EOS) {
  541.         if (lastIfdef != 0) {
  542.             if (!strcmp(lastIfdef, cond))
  543.                 return;
  544.             FlushIf(fp);
  545.         }
  546.         Fprintf(fp, "#if %s\n", lastIfdef = cond);
  547.     } else
  548.         FlushIf(fp);
  549. }
  550.  
  551. static void
  552. FlushIf(FILE *fp)
  553. {
  554.     if (lastIfdef != 0) {
  555.         Fprintf(fp, "#endif\n");
  556.         lastIfdef = 0;
  557.     }
  558. }
  559.  
  560. /******************************************************************************/
  561. /* get abbreviation by taking the uppercase chars only */
  562. static char *
  563. AbbrevMode(char *src)
  564. {
  565.     char *dst = StrAlloc(src);
  566.     register char    *s = src,
  567.             *d = dst;
  568.     while (*s) {
  569.         if (isUpper(*s))
  570.             *d++ = (char)toLower(*s);
  571.         s++;
  572.     }
  573.     *d = EOS;
  574.     return dst;
  575. }
  576.  
  577. /* get name, converted to lowercase */
  578. static char *
  579. NormalMode(char *src)
  580. {
  581.     char *dst = StrAlloc(src);
  582.     register char *s = dst;
  583.     while (*s) {
  584.         if (isUpper(*s))
  585.             *s = (char)toLower(*s);
  586.         s++;
  587.     }
  588.     return dst;
  589. }
  590.  
  591. /* given single-char type-key (cf: Mode2Key), return define-string */
  592. static const char *
  593. c2TYPE(int c)
  594. {
  595.     const char *value;
  596.     switch (c) {
  597.     case 'b':    value    = "BOOL";    break;
  598.     case 'e':    value    = "ENUM";    break;
  599.     case 'i':    value    = "INT";    break;
  600.     case 's':    value    = "STRING";    break;
  601.     case 'x':    value    = "REGEX";    break;
  602.     default:    value    = "?";
  603.     }
  604.     return value;
  605. }
  606.  
  607. static int
  608. is_majormode(const char *name)
  609. {
  610.     LIST *p;
  611.     for (p = all_mmodes; p != 0; p = p->nst) {
  612.         if (!strcmp(name, p->Name))
  613.             return TRUE;
  614.     }
  615.     return FALSE;
  616. }
  617.  
  618. /* check that the mode-name won't be illegal */
  619. static void
  620. CheckModes(char *name)
  621. {
  622.     if (!strncmp(name, "no", 2))
  623.         badfmt("illegal mode-name");
  624. }
  625.  
  626. /* make a sort-key for mode-name */
  627. static char *
  628. Mode2Key(char *type, char *name, char *cond, int submode)
  629. {
  630.     int    c;
  631.     char    *abbrev = AbbrevMode(name),
  632.         *normal = NormalMode(name),
  633.         *tmp = Alloc((unsigned)(4 + strlen(normal) + strlen(abbrev)));
  634.  
  635.     CheckModes(normal);
  636.     CheckModes(abbrev);
  637.  
  638.     switch (c = *type) {
  639.     case 'b':
  640.     case 'e':
  641.     case 'i':
  642.     case 's':    break;
  643.     case 'r':    c = 'x';    /* make this sort after strings */
  644.     }
  645.  
  646.     save_all_modes(type, normal, abbrev, cond);
  647.     if (submode)
  648.         save_all_submodes(type, normal, abbrev, cond);
  649.  
  650.     Sprintf(tmp, "%s\n%c\n%s", normal, c, abbrev);
  651. #if NO_LEAKS
  652.     free(normal);
  653.     free(abbrev);
  654. #endif
  655.     return tmp;
  656. }
  657.  
  658. /* converts a mode-name to a legal (hopefully unique!) symbol */
  659. static char *
  660. Name2Symbol(char *name)
  661. {
  662.     char    *base, *dst;
  663.     register char c;
  664.  
  665.     /* allocate enough for adjustment in 'Name2Address()' */
  666.     /*   "+ 10" for comfort */
  667.     base = dst = Alloc((unsigned)(strlen(name) + 10));
  668.  
  669.     *dst++ = 's';
  670.     *dst++ = '_';
  671.     while ((c = *name++) != EOS) {
  672.         if (c == '-')
  673.             c = '_';
  674.         *dst++ = c;
  675.     }
  676.     *dst++ = '_';
  677.     *dst++ = '_';
  678.     *dst = EOS;
  679.     return base;
  680. }
  681.  
  682. /* converts a mode-name & type to a reference to string-value */
  683. static char *
  684. Name2Address(
  685. char    *name,
  686. char    *type)
  687. {
  688.     /*  "+ 10" for comfort */
  689.         unsigned len = strlen(name) + 10;
  690.     char    *base = Alloc(len);
  691.     char    *temp;
  692.  
  693.     temp = Name2Symbol(name);
  694.     if (strlen(temp) + 1 + (isboolean(*type) ? 4 : 0) > len)
  695.         badfmt("bug: buffer overflow in Name2Address");
  696.  
  697.     (void)strcpy(base, temp);
  698.     if (isboolean(*type))
  699.         (void)strcat(strcat(strcpy(base+2, "no"), temp+2), "+2");
  700.     free(temp);
  701.     return base;
  702. }
  703.  
  704. /* define Member_Offset macro, used in index-definitions */
  705. static void
  706. DefineOffset(FILE *fp)
  707. {
  708. #if    OPT_IFDEF_MODES
  709.     Fprintf(fp,
  710. "#ifndef\tMember_Offset\n\
  711. #define\tMember_Offset(T, M)\t(((int)&(((T*)0)->M))/\\\n\
  712. \t\t\t\t ((int)&(((T*)0)->Q1) - (int)&(((T*)0)->s_MAX)))\n\
  713. #endif\n");
  714. #endif
  715. }
  716.  
  717. /* generate the index-struct (used for deriving ifdef-able index definitions) */
  718. static void
  719. WriteIndexStruct(
  720. FILE    *fp,
  721. LIST    *p,
  722. const char *ppref)
  723. {
  724. #if    OPT_IFDEF_MODES
  725.     char    *s,
  726.         temp[MAX_BUFFER],
  727.         line[MAX_BUFFER],
  728.         *vec[MAX_PARSE];
  729.  
  730.     BeginIf();
  731.     Fprintf(fp, "typedef\tstruct\t%c\n", L_CURL);
  732.     while (p != 0) {
  733.         WriteIf(fp, p->Cond);
  734.         (void)Parse(strcpy(line, p->Name), vec);
  735.         Sprintf(temp, "\tchar\t%s;", s = Name2Symbol(vec[1]));
  736.         free(s);
  737.         if (p->Note[0]) {
  738.             (void)PadTo(32, temp);
  739.             Sprintf(temp+strlen(temp), "/* %s */", p->Note);
  740.         }
  741.         Fprintf(fp, "%s\n", temp);
  742.         p = p->nst;
  743.     }
  744.  
  745.     FlushIf(fp);
  746.     Fprintf(fp, "\tchar\ts_MAX;\n");
  747.     Fprintf(fp, "\tchar\tQ1;\n");
  748.     Fprintf(fp, "\t%c Index%s;\n\n", R_CURL, ppref);
  749. #endif    /* OPT_IFDEF_MODES */
  750. }
  751.  
  752. /* generate the index-definitions */
  753. static void
  754. WriteModeDefines(
  755. LIST    *p,
  756. const char *ppref)
  757. {
  758.     char    temp[MAX_BUFFER],
  759.         line[MAX_BUFFER],
  760.         *vec[MAX_PARSE];
  761.     int    count    = 0;
  762. #if OPT_IFDEF_MODES
  763.     char    *s;
  764.     BeginIf();
  765. #endif
  766.  
  767.     for (; p != 0; p = p->nst, count++) {
  768.         (void)Parse(strcpy(line, p->Name), vec);
  769.         Sprintf(temp, "#define %.1s%s%s ",
  770.             (*ppref == 'B') ? "" : ppref,
  771.             (*vec[2] == 'b') ? "MD" : "VAL_",
  772.             p->Func);
  773.         (void)PadTo(24, temp);
  774. #if OPT_IFDEF_MODES
  775.         WriteIf(nemode, p->Cond);
  776.         Sprintf(temp+strlen(temp), "Member_Offset(Index%s, %s)",
  777.             ppref, s = Name2Symbol(vec[1]));
  778.         free(s);
  779. #else
  780.         Sprintf(temp+strlen(temp), "%d", count);
  781.         if (p->Note[0]) {
  782.             (void)PadTo(32, temp);
  783.             Sprintf(temp+strlen(temp), "/* %s */", p->Note);
  784.         }
  785. #endif /* OPT_IFDEF_MODES */
  786.         Fprintf(nemode, "%s\n", temp);
  787.     }
  788.  
  789.     Fprintf(nemode, "\n");
  790. #if OPT_IFDEF_MODES
  791.     FlushIf(nemode);
  792.     Sprintf(temp, "#define NUM_%c_VALUES\tMember_Offset(Index%s, s_MAX)",
  793.         *ppref, ppref);
  794. #else
  795.     Sprintf(temp, "#define NUM_%c_VALUES\t%d", *ppref, count);
  796. #endif /* OPT_IFDEF_MODES */
  797.  
  798.     (void)PadTo(32, temp);
  799.     Sprintf(temp+strlen(temp), "/* TABLESIZE(%c_valnames) -- %s */\n",
  800.         toLower(*ppref), ppref);
  801.     Fprintf(nemode, "%s", temp);
  802.     Fprintf(nemode, "#define MAX_%c_VALUES\t%d\n\n", *ppref, count);
  803. }
  804.  
  805. static void
  806. WriteModeSymbols(LIST *p)
  807. {
  808.     char    temp[MAX_BUFFER],
  809.         line[MAX_BUFFER];
  810.     char    *vec[MAX_PARSE],
  811.         *s;
  812.  
  813.     /* generate the symbol-table */
  814.     BeginIf();
  815.     while (p != 0) {
  816. #if OPT_IFDEF_MODES
  817.         WriteIf(nemode, p->Cond);
  818. #endif
  819.         (void)Parse(strcpy(line, p->Name), vec);
  820.         Sprintf(temp, "\t%c %s,",
  821.             L_CURL, s = Name2Address(vec[1], vec[2]));
  822.         (void)PadTo(32, temp);
  823.         free(s);
  824.         s = 0;
  825.  
  826.         Sprintf(temp+strlen(temp), "%s,",
  827.             *vec[3] ? (s = Name2Address(vec[3], vec[2])) : "\"X\"");
  828.         (void)PadTo(48, temp);
  829.         if (s != 0)
  830.             free(s);
  831.  
  832.         Sprintf(temp+strlen(temp), "VALTYPE_%s,", c2TYPE(*vec[2]));
  833.         (void)PadTo(64, temp);
  834.         if (!strcmp(p->Data, "0"))
  835.             (void)strcat(temp, "(ChgdFunc)0 },");
  836.         else
  837.             Sprintf(temp+strlen(temp), "%s },", p->Data);
  838.         Fprintf(nemode, "%s\n", temp);
  839.         p = p->nst;
  840.     }
  841.     FlushIf(nemode);
  842.  
  843. }
  844.  
  845. /******************************************************************************/
  846. static void
  847. save_all_modes(
  848.     const char *type,
  849.     char *normal,
  850.     const char *abbrev,
  851.     char *cond)
  852. {
  853.     if (isboolean(*type)) {
  854.         char    t_normal[LEN_BUFFER],
  855.             t_abbrev[LEN_BUFFER];
  856.         save_all_modes("Bool",
  857.             strcat(strcpy(t_normal, "no"), normal),
  858.             *abbrev
  859.                 ? strcat(strcpy(t_abbrev, "no"), abbrev)
  860.                 : "",
  861.             cond);
  862.     }
  863.     InsertSorted(&all_modes, normal, type, "", cond, "");
  864.     if (*abbrev)
  865.         InsertSorted(&all_modes, abbrev, type, "", cond, "");
  866. }
  867.  
  868. static void
  869. dump_all_modes(void)
  870. {
  871.     static const char *const top[] = {
  872.         "",
  873.         "#ifdef realdef",
  874.         "/*",
  875.         " * List of strings shared between all_modes, b_valnames and w_valnames",
  876.         " */",
  877.         "static const char",
  878.         };
  879.     static const char *const middle[] = {
  880.         "\ts_NULL[] = \"\";",
  881.         "#endif /* realdef */",
  882.         "",
  883.         "#ifdef realdef",
  884.         "EXTERN_CONST char *const all_modes[] = {",
  885.         };
  886.     static const char *const bottom[] = {
  887.         "\tNULL\t/* ends table */",
  888.         "};",
  889.         "#else",
  890.         "extern const char *const all_modes[];",
  891.         "#endif /* realdef */",
  892.         };
  893.     char    temp[MAX_BUFFER], *s;
  894.     register LIST *p, *q;
  895.  
  896.     InsertSorted(&all_modes, "all", "?", "", "", "");
  897.     write_lines(nemode, top);
  898.     BeginIf();
  899.     for (p = all_modes; p; p = p->nst) {
  900.         if (!isboolean(p->Func[0])) {
  901.             for (q = p->nst; q != 0; q = q->nst)
  902.                 if (!isboolean(q->Func[0]))
  903.                     break;
  904. #if OPT_IFDEF_MODES
  905.             WriteIf(nemode, p->Cond);
  906. #endif
  907.             Sprintf(temp, "\t%s[]",    s = Name2Symbol(p->Name));
  908.             (void)PadTo(32, temp);
  909.             free(s);
  910.             Sprintf(temp+strlen(temp), "= \"%s\",", p->Name);
  911.             (void)PadTo(64, temp);
  912.             Fprintf(nemode, "%s/* %s */\n", temp, p->Func);
  913.         }
  914.     }
  915.     FlushIf(nemode);
  916.  
  917.     write_lines(nemode, middle);
  918.     for (p = all_modes; p; p = p->nst) {
  919.         if (is_majormode(p->Name))
  920.             continue;
  921. #if OPT_IFDEF_MODES
  922.         WriteIf(nemode, p->Cond);
  923. #endif
  924.         Fprintf(nemode, "\t%s,\n", s = Name2Address(p->Name, p->Func));
  925.         free(s);
  926.     }
  927.     FlushIf(nemode);
  928.  
  929.     write_lines(nemode, bottom);
  930. }
  931.  
  932. /******************************************************************************/
  933. static void
  934. save_bindings(char *s, char *func, char *cond)
  935. {
  936.     int btype, c, highbit;
  937.  
  938.     btype = ASCIIBIND;
  939.  
  940.     if (*s == '^' && *(s+1) == 'A'&& *(s+2) == '-') {
  941.         btype = CTLABIND;
  942.         s += 3;
  943.     } else if (*s == 'F' && *(s+1) == 'N' && *(s+2) == '-') {
  944.         btype = SPECBIND;
  945.         s += 3;
  946.     } else if (*s == '^' && *(s+1) == 'X'&& *(s+2) == '-') {
  947.         btype = CTLXBIND;
  948.         s += 3;
  949.     }
  950.     if (*s == 'M' && *(s+1) == '-') {
  951.         highbit = 0x80;
  952.         s += 2;
  953.     } else {
  954.         highbit = 0;
  955.     }
  956.  
  957.     if (*s == '\\') { /* try for an octal value */
  958.         c = 0;
  959.         while (*++s < '8' && *s >= '0')
  960.             c = (c*8) + *s - '0';
  961.         if (c >= LEN_CHRSET)
  962.             badfmt("octal character too big");
  963.         c |= highbit;
  964.         set_binding(btype, c, cond, func);
  965.     } else if (*s == '^' && (c = *(s+1)) != EOS) { /* a control char? */
  966.         if (c > 'a' &&  c < 'z')
  967.             c = toUpper(c);
  968.         c = tocntrl(c);
  969.         c |= highbit;
  970.         set_binding(btype, c, cond, func);
  971.         s += 2;
  972.     } else if ((c = *s) != 0) {
  973.         c |= highbit;
  974.         set_binding(btype, c, cond, func);
  975.         s++;
  976.     } else {
  977.         badfmt("getting binding");
  978.     }
  979.  
  980.     if (*s != EOS)
  981.         badfmt("got extra characters");
  982. }
  983.  
  984. static void
  985. dump_bindings(void)
  986. {
  987.     char    temp[MAX_BUFFER];
  988.     const char *sctl, *meta;
  989.     int i, c, btype;
  990.     register LIST *p;
  991.  
  992.     btype = ASCIIBIND;
  993.  
  994.     Fprintf(nebind,"\nconst CMDFUNC *%s[%d] = %c\n",
  995.         tblname[btype], LEN_CHRSET, L_CURL);
  996.  
  997.     BeginIf();
  998.     for (i = 0; i < LEN_CHRSET; i++) {
  999.         WriteIf(nebind, conditions[i]);
  1000.  
  1001.         sctl = "";
  1002.         if (i & 0x80)
  1003.             meta = "meta-";
  1004.         else
  1005.             meta = "";
  1006.         c = i & 0x7f;
  1007.         if (c < ' ' || c > '~') {
  1008.             sctl = "ctrl-";
  1009.             c = toalpha(c);
  1010.         }
  1011.  
  1012.         if (bindings[i])
  1013.             Sprintf(temp, "\t&f_%s,", bindings[i]);
  1014.         else
  1015.             Sprintf(temp, "\tNULL,");
  1016.  
  1017.         Fprintf(nebind, "%s/* %s%s%c */\n", PadTo(32, temp),
  1018.                             meta, sctl, c);
  1019.         if (conditions[i] != 0)
  1020.             Fprintf(nebind,"#else\n\tNULL,\n");
  1021.         FlushIf(nebind);
  1022.  
  1023.     }
  1024.     Fprintf(nebind, "%c;\n", R_CURL);
  1025.  
  1026.     Fprintf(nebind,"\nKBIND kbindtbl[] = %c\n", L_CURL);
  1027.     BeginIf();
  1028.     for (p = all_kbind; p; p = p->nst) {
  1029.         WriteIf(nebind, p->Cond);
  1030.         Sprintf(temp, "\t%c %s,", L_CURL, p->Name);
  1031.         Fprintf(nebind, "%s&f_%s %c,\n",
  1032.             PadTo(32, temp), p->Func, R_CURL);
  1033.     }
  1034.     FlushIf(nebind);
  1035.     if (all_w32bind)
  1036.     {
  1037.         BeginIf();
  1038.         for (p = all_w32bind; p; p = p->nst) {
  1039.             WriteIf(nebind, p->Cond);
  1040.             Sprintf(temp, "\t%c %s,", L_CURL, p->Name);
  1041.             Fprintf(nebind, "%s&f_%s %c,\n",
  1042.             PadTo(32, temp), p->Func, R_CURL);
  1043.         }
  1044.         FlushIf(nebind);
  1045.     }
  1046.  
  1047.     Fprintf(nebind,"\t{ 0, NULL }\n");
  1048.     Fprintf(nebind,"%c;\n", R_CURL);
  1049.  
  1050. }
  1051.  
  1052. /******************************************************************************/
  1053. /*
  1054.  * Construct submode names for the given predefined majormodes
  1055.  */
  1056. static void
  1057. dump_majors(void)
  1058. {
  1059.     register LIST *p, *q;
  1060.     char    norm[LEN_BUFFER],
  1061.         abbr[LEN_BUFFER],
  1062.         type[LEN_BUFFER];
  1063.     char    normal[LEN_BUFFER],
  1064.         abbrev[LEN_BUFFER];
  1065.     char    *my_cond = "OPT_MAJORMODE";
  1066.  
  1067.     for (q = all_majors; q; q = q->nst) {
  1068.         Sprintf(normal, "%smode", q->Name);    /* FIXME */
  1069.         save_all_modes ("Major", normal, "", my_cond);
  1070.     }
  1071.     for (p = all_mmodes; p; p = p->nst) {
  1072.         if (sscanf(p->Name, "%s\n%s\n%s", norm, type, abbr) != 3)
  1073.             continue;
  1074.         for (q = all_majors; q; q = q->nst) {
  1075.             Sprintf(normal, "%s-%s", q->Name, norm);
  1076.             Sprintf(abbrev, "%s%s", q->Name, abbr);
  1077.             save_all_modes (c2TYPE(*type), normal, abbrev, my_cond);
  1078.         }
  1079.     }
  1080. }
  1081.  
  1082. /******************************************************************************/
  1083. static void
  1084. save_all_submodes (
  1085.     const char *type,
  1086.     char *normal,
  1087.     const char *abbrev,
  1088.     char *cond)
  1089. {
  1090.     if (isboolean(*type)) {
  1091.         char    t_normal[LEN_BUFFER],
  1092.             t_abbrev[LEN_BUFFER];
  1093.         save_all_submodes("Bool",
  1094.             strcat(strcpy(t_normal, "no"), normal),
  1095.             *abbrev
  1096.                 ? strcat(strcpy(t_abbrev, "no"), abbrev)
  1097.                 : "",
  1098.             cond);
  1099.     }
  1100.     InsertSorted(&all_submodes, normal, type, "", cond, "");
  1101.     if (*abbrev)
  1102.         InsertSorted(&all_submodes, abbrev, type, "", cond, "");
  1103. }
  1104.  
  1105. static void
  1106. save_mmodes(
  1107. char    *type,
  1108. char    **vec)
  1109. {
  1110.     char *key = Mode2Key(type, vec[1], vec[4], TRUE);
  1111.     InsertSorted(&all_mmodes, key, vec[2], vec[3], vec[4], vec[0]);
  1112. #if NO_LEAKS
  1113.     free(key);
  1114. #endif
  1115. }
  1116.  
  1117. static void
  1118. dump_mmodes(void)
  1119. {
  1120.     static const char *const top[] = {
  1121.         "",
  1122.         "#if OPT_MAJORMODE",
  1123.         "/* major mode flags\t*/",
  1124.         "/* the indices of M_VALUES.v[] */",
  1125.         };
  1126.     static const char *const middle[] = {
  1127.         "",
  1128.         "typedef struct M_VALUES {",
  1129.         "\t/* each entry is a val, and a ptr to a val */",
  1130.         "\tstruct VAL mv[MAX_M_VALUES+1];",
  1131.         "} M_VALUES;",
  1132.         "",
  1133.         "#ifdef realdef",
  1134.         "EXTERN_CONST struct VALNAMES m_valnames[MAX_M_VALUES+1] = {",
  1135.         };
  1136.     static const char *const bottom[] = {
  1137.         "",
  1138.         "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
  1139.         "};",
  1140.         "#else",
  1141.         "extern const struct VALNAMES m_valnames[MAX_M_VALUES+1];",
  1142.         "#endif",
  1143.         "#endif /* OPT_MAJORMODE */",
  1144.         };
  1145.  
  1146.     write_lines(nemode, top);
  1147.     WriteIndexStruct(nemode, all_mmodes, "Major");
  1148.     WriteModeDefines(all_mmodes, "Major");
  1149.     write_lines(nemode, middle);
  1150.     WriteModeSymbols(all_mmodes);
  1151.     write_lines(nemode, bottom);
  1152. }
  1153.  
  1154. static void
  1155. dump_all_submodes(void)
  1156. {
  1157.     static const char *const top[] = {
  1158.         "",
  1159.         "#if OPT_MAJORMODE",
  1160.         "#ifdef realdef",
  1161.         "EXTERN_CONST char *const all_submodes[] = {",
  1162.         };
  1163.     static const char *const bottom[] = {
  1164.         "\tNULL\t/* ends table */",
  1165.         "};",
  1166.         "#else",
  1167.         "extern const char *const all_submodes[];",
  1168.         "#endif /* realdef */",
  1169.         "#endif /* OPT_MAJORMODE */",
  1170.         };
  1171.     char    *s;
  1172.     register LIST *p;
  1173.  
  1174.     write_lines(nemode, top);
  1175.     for (p = all_submodes; p; p = p->nst) {
  1176.         if (is_majormode(p->Name))
  1177.             continue;
  1178. #if OPT_IFDEF_MODES
  1179.         WriteIf(nemode, p->Cond);
  1180. #endif
  1181.         Fprintf(nemode, "\t%s,\n", s = Name2Address(p->Name, p->Func));
  1182.         free(s);
  1183.     }
  1184.     FlushIf(nemode);
  1185.  
  1186.     write_lines(nemode, bottom);
  1187. }
  1188.  
  1189. /******************************************************************************/
  1190. static void
  1191. predefine_submodes(char **vec, int len)
  1192. {
  1193.     register LIST *p;
  1194.     int    found;
  1195.     char    norm[LEN_BUFFER],
  1196.         type[LEN_BUFFER],
  1197.         abbr[LEN_BUFFER],
  1198.         temp[LEN_BUFFER];
  1199.  
  1200.     if (len > 1) {
  1201.         for (p = all_majors, found = FALSE; p; p = p->nst) {
  1202.             if (!strcmp(p->Name, vec[2])) {
  1203.                 found = TRUE;
  1204.                 break;
  1205.             }
  1206.         }
  1207.         if (!found)
  1208.             InsertSorted(&all_majors, vec[2], "", "", "", "");
  1209.         if (len > 2) {
  1210.             for (p = all_bmodes, found = FALSE; p; p = p->nst) {
  1211.                 if (sscanf(p->Name, "%s\n%s\n%s",
  1212.                     norm, type, abbr) == 3
  1213.                  && (!strcmp(norm, vec[3])
  1214.                   || !strcmp(abbr, vec[3]))) {
  1215.                     found = TRUE;
  1216.                     break;
  1217.                 }
  1218.             }
  1219.             if (found) {
  1220.                 sprintf(temp, "%s-%s", vec[2], norm);
  1221.                 strcpy(norm, temp);
  1222.                 sprintf(temp, "%s%s", vec[2], abbr);
  1223.                 strcpy(abbr, temp);
  1224.                 save_all_modes(c2TYPE(*type), norm, abbr,
  1225.                     formcond(p->Cond, "OPT_MAJORMODE"));
  1226.             }
  1227.         }
  1228.     }
  1229. }
  1230.  
  1231. /******************************************************************************/
  1232. static void
  1233. save_bmodes(
  1234. char    *type,
  1235. char    **vec)
  1236. {
  1237.     char *key = Mode2Key(type, vec[1], vec[4], TRUE);
  1238.     InsertSorted(&all_bmodes, key, vec[2], vec[3], vec[4], vec[0]);
  1239. #if NO_LEAKS
  1240.     free(key);
  1241. #endif
  1242. }
  1243.  
  1244. static void
  1245. dump_bmodes(void)
  1246. {
  1247.     static const char *const top[] = {
  1248.         "",
  1249.         "/* buffer mode flags\t*/",
  1250.         "/* the indices of B_VALUES.v[] */",
  1251.         };
  1252.     static const char *const middle[] = {
  1253.         "",
  1254.         "typedef struct B_VALUES {",
  1255.         "\t/* each entry is a val, and a ptr to a val */",
  1256.         "\tstruct VAL bv[MAX_B_VALUES+1];",
  1257.         "} B_VALUES;",
  1258.         "",
  1259.         "#ifdef realdef",
  1260.         "EXTERN_CONST struct VALNAMES b_valnames[] = {",
  1261.         };
  1262.     static const char *const bottom[] = {
  1263.         "",
  1264.         "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
  1265.         "};",
  1266.         "#else",
  1267.         "extern const struct VALNAMES b_valnames[];",
  1268.         "#endif",
  1269.         };
  1270.  
  1271.     write_lines(nemode, top);
  1272.     WriteIndexStruct(nemode, all_bmodes, "Buffers");
  1273.     WriteModeDefines(all_bmodes, "Buffers");
  1274.     write_lines(nemode, middle);
  1275.     WriteModeSymbols(all_bmodes);
  1276.     write_lines(nemode, bottom);
  1277. }
  1278.  
  1279. /******************************************************************************/
  1280. static void
  1281. start_vars_h(char **argv)
  1282. {
  1283.     static const char *const head[] = {
  1284.         "",
  1285.         "#if OPT_EVAL",
  1286.         "",
  1287.         "/*\tstructure to hold user variables and their definitions\t*/",
  1288.         "",
  1289.         "typedef struct UVAR {",
  1290.         "\tstruct UVAR *next;",
  1291.         "\tchar *u_name;\t\t/* name of user variable */",
  1292.         "\tchar *u_value;\t\t\t\t/* value (string) */",
  1293.         "} UVAR;",
  1294.         "",
  1295.         "decl_uninit( UVAR *user_vars );\t/* user variables */",
  1296.         "",
  1297.         };
  1298.  
  1299.     if (!nevars) {
  1300.         nevars = OpenHeader("nevars.h", argv);
  1301.         write_lines(nevars, head);
  1302.     }
  1303. }
  1304.  
  1305. static void
  1306. finish_vars_h(void)
  1307. {
  1308.     if (nevars)
  1309.         Fprintf(nevars, "\n#endif /* OPT_EVAL */\n");
  1310. }
  1311.  
  1312. /******************************************************************************/
  1313. static void
  1314. init_envars(void)
  1315. {
  1316.     static const char *const head[] = {
  1317.         "",
  1318.         "/*\tlist of recognized environment variables\t*/",
  1319.         "",
  1320.         "#ifdef realdef",
  1321.         "EXTERN_CONST char *const envars[] = {"
  1322.         };
  1323.     static    int    done;
  1324.  
  1325.     if (!done++)
  1326.         write_lines(nevars, head);
  1327. }
  1328.  
  1329. static void
  1330. save_envars(char **vec)
  1331. {
  1332.     /* insert into 'all_modes' to provide for common name-completion
  1333.      * table, and into 'all_envars' to get name/index correspondence.
  1334.      */
  1335.     InsertSorted(&all_modes,  vec[1], "env",  "", formcond("OPT_EVAL", vec[3]), "");
  1336.     InsertSorted(&all_envars, vec[1], vec[2], "", vec[3], vec[0]);
  1337. }
  1338.  
  1339. static void
  1340. dump_envars(void)
  1341. {
  1342.     static const char *const middle[] = {
  1343.         "\tNULL\t/* ends table for name-completion */",
  1344.         "};",
  1345.         "#else",
  1346.         "extern const char *const envars[];",
  1347.         "#endif",
  1348.         "",
  1349.         "/* \tand its preprocesor definitions\t\t*/",
  1350.         ""
  1351.         };
  1352.     char    temp[MAX_BUFFER];
  1353.     register LIST *p;
  1354.     register int count;
  1355. #if OPT_IFDEF_MODES
  1356.     char    *s;
  1357. #endif
  1358.  
  1359.     BeginIf();
  1360.     for (p = all_envars, count = 0; p != 0; p = p->nst) {
  1361.         if (!count++)
  1362.             init_envars();
  1363. #if OPT_IFDEF_MODES
  1364.         WriteIf(nevars, p->Cond);
  1365. #endif
  1366.         Fprintf(nevars, "\t%s,\n", s = Name2Symbol(p->Name));
  1367.         free(s);
  1368.     }
  1369.     FlushIf(nevars);
  1370.  
  1371.     for (p = all_envars, count = 0; p != 0; p = p->nst) {
  1372.         if (!count++) {
  1373.             write_lines(nevars, middle);
  1374.             BeginIf();
  1375.             WriteIndexStruct(nevars, all_envars, "Vars");
  1376.         }
  1377. #if OPT_IFDEF_MODES
  1378.         WriteIf(nevars, p->Cond);
  1379.         Sprintf(temp, "#define\tEV%s", p->Func);
  1380.         (void)PadTo(24, temp);
  1381.         Sprintf(temp + strlen(temp), "Member_Offset(IndexVars, %s)",
  1382.             s = Name2Symbol(p->Name));
  1383.         free(s);
  1384.         Fprintf(nevars, "%s\n", temp);
  1385. #else
  1386.         Sprintf(temp, "#define\tEV%s", p->Func);
  1387.         Fprintf(nevars, "%s%d\n", PadTo(24, temp), count-1);
  1388. #endif
  1389.     }
  1390.     FlushIf(nevars);
  1391. }
  1392.  
  1393. /******************************************************************************/
  1394. static void
  1395. save_fsms(char **vec)
  1396. {
  1397.     InsertSorted(&all_fsms, vec[1], "", vec[2], vec[3], vec[0]);
  1398. }
  1399.  
  1400. static void
  1401. init_fsms(void)
  1402. {
  1403.     char name[BUFSIZ];
  1404.     int n;
  1405.  
  1406.     if (fsm_name == 0)
  1407.         badfmt("Missing table name");
  1408.  
  1409.     (void)strcpy(name, fsm_name);
  1410.     for (n = 0; fsm_name[n] != '\0'; n++)
  1411.         fsm_name[n] = toUpper(fsm_name[n]);
  1412.     fprintf(nefsms, "\n");
  1413.     fprintf(nefsms, "#if OPT_%s_CHOICES\n", fsm_name);
  1414.     fprintf(nefsms, "static const\n");
  1415.     fprintf(nefsms, "FSM_CHOICES fsm_%s_choices[] = %c\n", name, L_CURL);
  1416. }
  1417.  
  1418. static void
  1419. dump_fsms(void)
  1420. {
  1421.     static const char *const middle[] = {
  1422.         "\tEND_CHOICES\t/* ends table for name-completion */",
  1423.         "};",
  1424.         };
  1425.     char    temp[MAX_BUFFER];
  1426.     register LIST *p;
  1427.     register int count;
  1428.  
  1429.     if (all_fsms != 0) {
  1430.         BeginIf();
  1431.         for (p = all_fsms, count = 0; p != 0; p = p->nst) {
  1432.             if (!count++)
  1433.                 init_fsms();
  1434. #if OPT_IFDEF_MODES
  1435.             WriteIf(nefsms, p->Cond);
  1436. #endif
  1437.             Sprintf(temp, "\t{ \"%s\",", p->Name);
  1438.             Fprintf(nefsms, "%s%s },\n", PadTo(40, temp), p->Data);
  1439.         }
  1440.         FlushIf(nefsms);
  1441.  
  1442.         write_lines(nefsms, middle);
  1443.         Fprintf(nefsms, "#endif /* OPT_%s_CHOICES */\n", fsm_name);
  1444.  
  1445.         free_LIST(&all_fsms);
  1446.  
  1447.         free(fsm_name);
  1448.         fsm_name = 0;
  1449.     }
  1450. }
  1451.  
  1452. /******************************************************************************/
  1453. static void
  1454. start_fsms_h(char **argv, char *name)
  1455. {
  1456.     static const char *const head[] = {
  1457.         "#if OPT_ENUM_MODES",
  1458.         "",
  1459.         "#define ENUM_ILLEGAL   (-2)",
  1460.         "#define ENUM_UNKNOWN   (-1)",
  1461.         "#define END_CHOICES    { (char *)0, ENUM_ILLEGAL }",
  1462.         "",
  1463.         "typedef struct {",
  1464.         "\tconst char * choice_name;",
  1465.         "\tint    choice_code;",
  1466.         "} FSM_CHOICES;",
  1467.         "",
  1468.         "struct FSM {",
  1469.         "\tconst char * mode_name;",
  1470.         "\tconst FSM_CHOICES * choices;",
  1471.         "};"
  1472.         };
  1473.  
  1474.     if (!nefsms) {
  1475.         nefsms = OpenHeader("nefsms.h", argv);
  1476.         write_lines(nefsms, head);
  1477.     }
  1478.     dump_fsms();
  1479.     fsm_name = StrAlloc(name);
  1480. }
  1481.  
  1482. static void
  1483. finish_fsms_h(void)
  1484. {
  1485.     if (nefsms)
  1486.         Fprintf(nefsms, "\n#endif /* OPT_ENUM_MODES */\n");
  1487. }
  1488.  
  1489. /******************************************************************************/
  1490. static void
  1491. dump_execs(FILE *fp, int count)
  1492. {
  1493.     int n;
  1494.     for (n = 1; n <= count; n++) {
  1495.         Fprintf(fp, "#if OPT_EXEC_MACROS>%d\n", n-1);
  1496.         Fprintf(fp, "int\n");
  1497.         Fprintf(fp, "cbuf%d(int f, int n)\n", n);
  1498.         Fprintf(fp, "{\n\treturn cbuf(f, n, %d);\n}\n", n);
  1499.         Fprintf(fp, "#endif\n");
  1500.     }
  1501.     fclose(fp);
  1502. }
  1503.  
  1504. /******************************************************************************/
  1505. static void
  1506. save_funcs(
  1507. char    *func,
  1508. char    *flags,
  1509. char    *cond,
  1510. char    *old_cond,
  1511. char    *help)
  1512. {
  1513.     char    temp[MAX_BUFFER];
  1514.     register char    *s;
  1515.  
  1516.     if (strcmp(cond, old_cond)) {
  1517.         if (*old_cond) {
  1518.             SaveEndif(all_funcs);
  1519.             SaveEndif(all__FUNCs);
  1520.             SaveEndif(all__CMDFs);
  1521.         }
  1522.         if (*cond) {
  1523.             Sprintf(temp, "#if %s", cond);
  1524.             InsertOnEnd(&all_funcs, temp);
  1525.             InsertOnEnd(&all__FUNCs, temp);
  1526.             InsertOnEnd(&all__CMDFs, temp);
  1527.         }
  1528.         (void)strcpy(old_cond, cond);
  1529.     }
  1530.     Sprintf(temp, "extern int %s ( int f, int n );", func);
  1531.     InsertOnEnd(&all_funcs, temp);
  1532.  
  1533.     s = append(strcpy(temp, "\tEXTERN_CONST CMDFUNC f_"), func);
  1534.     (void)PadTo(32, temp);
  1535.     s = append(s, "= {\n\tINIT_UNION(");
  1536.     s = append(s, func);
  1537.     s = append(s, "),\n\t");
  1538.     s = append(s, flags);
  1539.     s = append(s, "\n#if OPT_ONLINEHELP\n\t\t,\"");
  1540.     s = append(s, help);
  1541.     (void)append(s, "\"\n#endif\n };");
  1542.     InsertOnEnd(&all__FUNCs, temp);
  1543.  
  1544.     s = append(strcpy(temp, "extern const CMDFUNC f_"), func);
  1545.     (void)append(s, ";");
  1546.     InsertOnEnd(&all__CMDFs, temp);
  1547. }
  1548.  
  1549. static void
  1550. dump_funcs(
  1551. FILE    *fp,
  1552. LIST    *head)
  1553. {
  1554.     register LIST *p;
  1555.     for (p = head; p != 0; p = p->nst)
  1556.         Fprintf(fp, "%s\n", p->Name);
  1557. }
  1558.  
  1559. /******************************************************************************/
  1560. static void
  1561. save_gmodes(
  1562. char    *type,
  1563. char    **vec)
  1564. {
  1565.     char *key = Mode2Key(type, vec[1], vec[4], FALSE);
  1566.     InsertSorted(&all_gmodes, key, vec[2], vec[3], vec[4], vec[0]);
  1567. #if NO_LEAKS
  1568.     free(key);
  1569. #endif
  1570. }
  1571.  
  1572. static void
  1573. dump_gmodes(void)
  1574. {
  1575.     static const char *const top[] = {
  1576.         "",
  1577.         "/* global mode flags\t*/",
  1578.         "/* the indices of G_VALUES.v[] */",
  1579.         };
  1580.     static const char *const middle[] = {
  1581.         "",
  1582.         "typedef struct G_VALUES {",
  1583.         "\t/* each entry is a val, and a ptr to a val */",
  1584.         "\tstruct VAL gv[MAX_G_VALUES+1];",
  1585.         "} G_VALUES;",
  1586.         "",
  1587.         "#ifdef realdef",
  1588.         "EXTERN_CONST struct VALNAMES g_valnames[] = {",
  1589.         };
  1590.     static const char *const bottom[] = {
  1591.         "",
  1592.         "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
  1593.         "};",
  1594.         "#else",
  1595.         "extern const struct VALNAMES g_valnames[];",
  1596.         "#endif",
  1597.         };
  1598.  
  1599.     write_lines(nemode, top);
  1600.     WriteIndexStruct(nemode, all_gmodes, "Globals");
  1601.     WriteModeDefines(all_gmodes, "Globals");
  1602.     write_lines(nemode, middle);
  1603.     WriteModeSymbols(all_gmodes);
  1604.     write_lines(nemode, bottom);
  1605. }
  1606.  
  1607. /******************************************************************************/
  1608. static void
  1609. save_names(char *name, char *func, char *cond)
  1610. {
  1611.     InsertSorted(&all_names, name, func, "", cond, "");
  1612. }
  1613.  
  1614. static void
  1615. dump_names(void)
  1616. {
  1617.     register LIST *m;
  1618.     char    temp[MAX_BUFFER];
  1619.  
  1620.     Fprintf(nename,"\n/* if you maintain this by hand, keep it in */\n");
  1621.     Fprintf(nename,"/* alphabetical order!!!! */\n\n");
  1622.     Fprintf(nename,"EXTERN_CONST NTAB nametbl[] = {\n");
  1623.  
  1624.     BeginIf();
  1625.     for (m = all_names; m != NULL; m = m->nst) {
  1626.         WriteIf(nename, m->Cond);
  1627.         Sprintf(temp, "\t{ \"%s\",", m->Name);
  1628.         Fprintf(nename, "%s&f_%s },\n", PadTo(40, temp), m->Func);
  1629.     }
  1630.     FlushIf(nename);
  1631.     Fprintf(nename,"\t{ NULL, NULL }\n};\n");
  1632. }
  1633.  
  1634. /******************************************************************************/
  1635. static void
  1636. init_ufuncs(void)
  1637. {
  1638.     static const char *const head[] = {
  1639.         "",
  1640.         "/*\tlist of recognized user functions\t*/",
  1641.         "",
  1642.         "typedef struct UFUNC {",
  1643.         "\tconst char *f_name;\t/* name of function */",
  1644.         "\tint f_type;\t/* 1 = monamic, 2 = dynamic */",
  1645.         "} UFUNC;",
  1646.         "",
  1647.         "#define\tNILNAMIC\t0",
  1648.         "#define\tMONAMIC\t\t1",
  1649.         "#define\tDYNAMIC\t\t2",
  1650.         "#define\tTRINAMIC\t3",
  1651.         "",
  1652.         "#ifdef realdef",
  1653.         "EXTERN_CONST UFUNC funcs[] = {",
  1654.         };
  1655.     static    int    done;
  1656.  
  1657.     if (!done++)
  1658.         write_lines(nevars, head);
  1659. }
  1660.  
  1661. static void
  1662. save_ufuncs(char **vec)
  1663. {
  1664.     InsertSorted(&all_ufuncs, vec[1], vec[2], vec[3], "", vec[0]);
  1665. }
  1666.  
  1667. static void
  1668. dump_ufuncs(void)
  1669. {
  1670.     static    const char    *const middle[] = {
  1671.         "};",
  1672.         "#else",
  1673.         "extern const UFUNC funcs[];",
  1674.         "#endif",
  1675.         "",
  1676.         "/* \tand its preprocesor definitions\t\t*/",
  1677.         "",
  1678.         };
  1679.     char    temp[MAX_BUFFER];
  1680.     register LIST *p;
  1681.     register int    count;
  1682.  
  1683.     for (p = all_ufuncs, count = 0; p != 0; p = p->nst) {
  1684.         if (!count++)
  1685.             init_ufuncs();
  1686.         Sprintf(temp, "\t{\"%s\",", p->Name);
  1687.         (void)PadTo(15, temp);
  1688.         Sprintf(temp+strlen(temp), "%s},", p->Data);
  1689.         if (p->Note[0]) {
  1690.             (void)PadTo(32, temp);
  1691.             Sprintf(temp+strlen(temp), "/* %s */", p->Note);
  1692.         }
  1693.         Fprintf(nevars, "%s\n", temp);
  1694.     }
  1695.     for (p = all_ufuncs, count = 0; p != 0; p = p->nst) {
  1696.         if (!count)
  1697.             write_lines(nevars, middle);
  1698.         Sprintf(temp, "#define\tUF%s", p->Func);
  1699.         Fprintf(nevars, "%s%d\n", PadTo(24, temp), count++);
  1700.     }
  1701.     Fprintf(nevars, "\n#define\tNFUNCS\t\t%d\n", count);
  1702. }
  1703.  
  1704. /******************************************************************************/
  1705. static void
  1706. save_wmodes(
  1707. char    *type,
  1708. char    **vec)
  1709. {
  1710.     char *key = Mode2Key(type, vec[1], vec[4], FALSE);
  1711.     InsertSorted(&all_wmodes, key, vec[2], vec[3], vec[4], vec[0]);
  1712. #if NO_LEAKS
  1713.     free(key);
  1714. #endif
  1715. }
  1716.  
  1717. static void
  1718. dump_wmodes(void)
  1719. {
  1720.     static const char *top[] = {
  1721.         "",
  1722.         "/* these are the boolean, integer, and pointer value'd settings that are",
  1723.         "\tassociated with a window, and usually settable by a user.  There",
  1724.         "\tis a global set that is inherited into a buffer, and its windows",
  1725.         "\tin turn are inherit the buffer's set. */",
  1726.         };
  1727.     static const char *middle[] = {
  1728.         "",
  1729.         "typedef struct W_VALUES {",
  1730.         "\t/* each entry is a val, and a ptr to a val */",
  1731.         "\tstruct VAL wv[MAX_W_VALUES+1];",
  1732.         "} W_VALUES;",
  1733.         "",
  1734.         "#ifdef realdef",
  1735.         "EXTERN_CONST struct VALNAMES w_valnames[] = {",
  1736.         };
  1737.     static const char *bottom[] = {
  1738.         "",
  1739.         "\t{ NULL,\tNULL,\tVALTYPE_INT, 0 }",
  1740.         "};",
  1741.         "#else",
  1742.         "extern const struct VALNAMES w_valnames[];",
  1743.         "#endif",
  1744.         };
  1745.  
  1746.     write_lines(nemode, top);
  1747.     WriteIndexStruct(nemode, all_wmodes, "Windows");
  1748.     WriteModeDefines(all_wmodes, "Windows");
  1749.     write_lines(nemode, middle);
  1750.     WriteModeSymbols(all_wmodes);
  1751.     write_lines(nemode, bottom);
  1752. }
  1753.  
  1754.  
  1755. /* The accepted format for a Win32 special key binding is:
  1756.  *
  1757.  *    {<modifier>+}...<key>
  1758.  *
  1759.  * where:
  1760.  *
  1761.  *    <modifier> := SHIFT | CTRL | ALT
  1762.  *
  1763.  *    <key>      := Insert | 6
  1764.  *
  1765.  * See the comments at the end of the file "cmdtbl" for a complete
  1766.  * explanation of why more <key>'s are not supported.
  1767.  *
  1768.  *                   Caution
  1769.  *                   -------
  1770.  * The error checking supplied in mkw32binding() and InsertSorted() can
  1771.  * be fooled.
  1772.  */
  1773. #ifdef _WIN32
  1774. static void
  1775. mkw32binding(char *key, char *defn, char *conditional, char *func, char *fcond)
  1776. {
  1777. #define KEYTOKEN "W32_KEY"
  1778.  
  1779.     char *cp = key, *match, *tmp, *defp, cum_defn[512];
  1780.     int  nomore_keys, saw_modifier;
  1781.  
  1782.     strcpy(cum_defn, KEYTOKEN);
  1783.     defp        = cum_defn + sizeof(KEYTOKEN) - 1;
  1784.     nomore_keys = saw_modifier = 0;
  1785.     while (*cp)
  1786.     {
  1787.     nomore_keys = 1;  /* An assumption. */
  1788.     if ((tmp = strchr(cp, '+')) != NULL)
  1789.         *tmp  = '\0';
  1790.     match = NULL;
  1791.     if (stricmp(cp, "shift") == 0)
  1792.     {
  1793.         match     = "W32_SHIFT";
  1794.         nomore_keys  = 0;            /* Okay to stack modifiers */
  1795.         saw_modifier = 1;
  1796.     }
  1797.     else if (stricmp(cp, "alt") == 0)
  1798.     {
  1799.         match     = "W32_ALT";
  1800.         nomore_keys  = 0;            /* Okay to stack modifiers */
  1801.         saw_modifier = 1;
  1802.     }
  1803.     else if (stricmp(cp, "ctrl") == 0)
  1804.     {
  1805.         match     = "W32_CTRL";
  1806.         nomore_keys  = 0;            /* Okay to stack modifiers */
  1807.         saw_modifier = 1;
  1808.     }
  1809.     else if (stricmp(cp, "insert") == 0)
  1810.         match    = "VK_INSERT";
  1811.     if (match)
  1812.     {
  1813.         defp += sprintf(defp, "|%s", match);
  1814.         if (! tmp)
  1815.         break;
  1816.         cp = tmp + 1;
  1817.     }
  1818.     else if (*cp == '6')
  1819.         defp += sprintf(defp, "|'%c'", *cp++);
  1820.     if (*cp && nomore_keys)
  1821.         badfmt("invalid/unsupported Win32 key sequence");
  1822.     }
  1823.     if (! saw_modifier)
  1824.     badfmt("missing Win32 key modifier");
  1825.     InsertSorted(&all_w32bind,
  1826.          cum_defn,
  1827.          func,
  1828.          "",
  1829.          formcond(fcond, conditional),
  1830.          "");
  1831. #undef KEYTOKEN
  1832. }
  1833. #else    /* Not a Win32 host -> dummy function -- doesn't do a thing */
  1834. #define mkw32binding(key, defn, conditional, func, fcond) /*EMPTY*/
  1835. #endif  /* _WIN32 */
  1836.  
  1837. /******************************************************************************/
  1838. static void
  1839. free_LIST (LIST **p)
  1840. {
  1841.     LIST    *q;
  1842.  
  1843.     while ((q = *p) != 0) {
  1844.         *p = q->nst;
  1845.         if (q->Name != Blank) FreeIfNeeded(q->Name);
  1846.         if (q->Func != Blank) FreeIfNeeded(q->Func);
  1847.         if (q->Data != Blank) FreeIfNeeded(q->Data);
  1848.         if (q->Cond != Blank) FreeIfNeeded(q->Cond);
  1849.         if (q->Note != Blank) FreeIfNeeded(q->Note);
  1850.         free((char *)q);
  1851.     }
  1852. }
  1853.  
  1854. #if NO_LEAKS
  1855. /*
  1856.  * Free all memory allocated within 'mktbls'. This is used both for debugging
  1857.  * as well as for allowing 'mktbls' to be an application procedure that is
  1858.  * repeatedly invoked from a GUI.
  1859.  */
  1860. static void
  1861. free_mktbls (void)
  1862. {
  1863.     register int k;
  1864.  
  1865.     free_LIST(&all_names);
  1866.     free_LIST(&all_funcs);
  1867.     free_LIST(&all__FUNCs);
  1868.     free_LIST(&all__CMDFs);
  1869.     free_LIST(&all_envars);
  1870.     free_LIST(&all_ufuncs);
  1871.     free_LIST(&all_modes);
  1872.     free_LIST(&all_submodes);
  1873.     free_LIST(&all_kbind);
  1874.     free_LIST(&all_w32bind);
  1875.     free_LIST(&all_gmodes);
  1876.     free_LIST(&all_mmodes);
  1877.     free_LIST(&all_bmodes);
  1878.     free_LIST(&all_wmodes);
  1879.  
  1880.     for (k = 0; k < LEN_CHRSET; k++) {
  1881.         FreeIfNeeded(bindings[k]);
  1882.         FreeIfNeeded(conditions[k]);
  1883.     }
  1884. #if DOALLOC
  1885.     show_alloc();
  1886. #endif
  1887. }
  1888. #else
  1889. #define free_mktbls()
  1890. #endif    /* NO_LEAKS */
  1891.  
  1892. /******************************************************************************/
  1893. int
  1894. main(int argc, char *argv[])
  1895. {
  1896.     char *vec[MAX_PARSE];
  1897.     char line[MAX_BUFFER];
  1898.     char func[LEN_BUFFER];
  1899.     char flags[LEN_BUFFER];
  1900.     char funchelp[MAX_BUFFER];
  1901.     char old_fcond[LEN_BUFFER],    fcond[LEN_BUFFER];
  1902.     char modetype[LEN_BUFFER];
  1903.     int section;
  1904.     int r;
  1905.  
  1906.     func[0] = flags[0] = fcond[0] = old_fcond[0] = modetype[0] = EOS;
  1907.  
  1908.     if (setjmp(my_top))
  1909.         ReturnFromMain(BADEXIT);
  1910.  
  1911.     if (argc != 2) {
  1912.         Fprintf(stderr, "usage: mktbls cmd-file\n");
  1913.         longjmp(my_top,1);
  1914.     }
  1915.  
  1916.     if ((cmdtbl = fopen(inputfile = argv[1],"r")) == NULL ) {
  1917.         Fprintf(stderr,"mktbls: couldn't open cmd-file\n");
  1918.         longjmp(my_top,1);
  1919.     }
  1920.  
  1921.     *old_fcond = EOS;
  1922.     section = SECT_CMDS;
  1923.  
  1924.     /* process each input line */
  1925.     while (fgets(line, sizeof(line), cmdtbl) != NULL) {
  1926.         char    col0    = line[0],
  1927.             col1    = line[1];
  1928.  
  1929.         l++;
  1930.         r = Parse(line, vec);
  1931.  
  1932.         switch (col0) {
  1933.         case '#':        /* comment */
  1934.         case '\n':        /* empty-list */
  1935.             break;
  1936.  
  1937.         case '.':        /* a new section */
  1938.             switch (col1) {
  1939.             case 'c':
  1940.                 section = SECT_CMDS;
  1941.                 break;
  1942.             case 'e':
  1943.                 section = SECT_VARS;
  1944.                 start_vars_h(argv);
  1945.                 break;
  1946.             case 'f':
  1947.                 section = SECT_FUNC;
  1948.                 start_vars_h(argv);
  1949.                 break;
  1950.             case 'g':
  1951.                 section = SECT_GBLS;
  1952.                 break;
  1953.             case 'm':
  1954.                 section = SECT_MAJR;
  1955.                 predefine_submodes(vec, r);
  1956.                 break;
  1957.             case 'b':
  1958.                 section = SECT_BUFF;
  1959.                 break;
  1960.             case 't':
  1961.                 section = SECT_FSMS;
  1962.                 start_fsms_h(argv, vec[2]);
  1963.                 break;
  1964.             case 'w':
  1965.                 section = SECT_WIND;
  1966.                 break;
  1967.             default:
  1968.                 badfmt("unknown section");
  1969.             }
  1970.             break;
  1971.  
  1972.         case '\t':        /* a new function */
  1973.             switch (section) {
  1974.             case SECT_CMDS:
  1975.                 switch (col1) {
  1976.                 case '"':    /* then it's an english name */
  1977.                     if (r < 1 || r > 2)
  1978.                         badfmt("looking for english name");
  1979.  
  1980.                     save_names(vec[1], func, formcond(fcond,vec[2]));
  1981.                     break;
  1982.  
  1983.                 case '\'':    /* then it's a key */
  1984.                     if (r < 1 || r > 3)
  1985.                         badfmt("looking for key binding");
  1986.  
  1987.                     if (strcmp("W32KY", vec[2]) == 0)
  1988.                     {
  1989.                         mkw32binding(vec[1], vec[2], vec[3], func, fcond);
  1990.                     }
  1991.                     else
  1992.                     {
  1993.                         if (strncmp("KEY_",vec[2],4) == 0)
  1994.                         {
  1995.                             if (strncmp("FN-",vec[1],3) != 0)
  1996.                                 badfmt("KEY_xxx definition must for FN- binding");
  1997.                             if (!nefkeys)
  1998.                                     nefkeys = OpenHeader("nefkeys.h", argv);
  1999.                             Fprintf(nefkeys, "#define %16s (SPEC|'%s')\n",
  2000.                                     vec[2],vec[1]+3);
  2001.                             vec[2] = vec[3];
  2002.                         }
  2003.                         save_bindings(vec[1], func, formcond(fcond,vec[2]));
  2004.                     }
  2005.                     break;
  2006.  
  2007.                 case '<':    /* then it's a help string */
  2008.                     /* put code here. */
  2009.                     (void)strcpy(funchelp, vec[1]);
  2010.                     break;
  2011.  
  2012.                 default:
  2013.                     badfmt("bad line");
  2014.                 }
  2015.                 break;
  2016.  
  2017.             case SECT_GBLS:
  2018.                 if (r < 2 || r > 4)
  2019.                     badfmt("looking for GLOBAL modes");
  2020.                 save_gmodes(modetype, vec);
  2021.                 break;
  2022.  
  2023.             case SECT_MAJR:
  2024.                 if (r < 2 || r > 4)
  2025.                     badfmt("looking for MAJOR modes");
  2026.                 save_mmodes(modetype, vec);
  2027.                 break;
  2028.  
  2029.             case SECT_BUFF:
  2030.                 if (r < 2 || r > 4)
  2031.                     badfmt("looking for BUFFER modes");
  2032.                 save_bmodes(modetype, vec);
  2033.                 break;
  2034.  
  2035.             case SECT_WIND:
  2036.                 if (r < 2 || r > 4)
  2037.                     badfmt("looking for WINDOW modes");
  2038.                 save_wmodes(modetype, vec);
  2039.                 break;
  2040.  
  2041.             default:
  2042.                 badfmt("did not expect a tab");
  2043.             }
  2044.             break;
  2045.  
  2046.         default:        /* cache information about funcs */
  2047.             switch (section) {
  2048.             case SECT_CMDS:
  2049.                 if (r < 2 || r > 3)
  2050.                     badfmt("looking for new function");
  2051.  
  2052.                 /* don't save this yet -- we may get a
  2053.                     a help line for it.  save the previous
  2054.                     one now, and hang onto this one */
  2055.                 if (func[0]) { /* flush the old one */
  2056.                     save_funcs( func, flags, fcond,
  2057.                         old_fcond, funchelp);
  2058.                     funchelp[0] = EOS;
  2059.                 }
  2060.                 (void)strcpy(func,  vec[1]);
  2061.                 (void)strcpy(flags, vec[2]);
  2062.                 (void)strcpy(fcond, vec[3]);
  2063.                 break;
  2064.  
  2065.             case SECT_FSMS:
  2066.                 save_fsms(vec);
  2067.                 break;
  2068.  
  2069.             case SECT_VARS:
  2070.                 if (r < 2 || r > 3)
  2071.                     badfmt("looking for char *envars[]");
  2072.                 save_envars(vec);
  2073.                 break;
  2074.  
  2075.             case SECT_FUNC:
  2076.                 if (r < 2 || r > 3)
  2077.                     badfmt("looking for UFUNC func[]");
  2078.                 save_ufuncs(vec);
  2079.                 break;
  2080.  
  2081.             case SECT_GBLS:
  2082.             case SECT_MAJR:
  2083.             case SECT_BUFF:
  2084.             case SECT_WIND:
  2085.                 if (r != 1
  2086.                  || (!strcmp(vec[1], "bool")
  2087.                   && !strcmp(vec[1], "enum")
  2088.                   && !strcmp(vec[1], "int")
  2089.                   && !strcmp(vec[1], "string")
  2090.                   && !strcmp(vec[1], "regex")))
  2091.                     badfmt("looking for mode datatype");
  2092.                 (void)strcpy(modetype, vec[1]);
  2093.                 break;
  2094.  
  2095.             default:
  2096.                 badfmt("section not implemented");
  2097.             }
  2098.         }
  2099.     }
  2100.  
  2101.     if (func[0]) { /* flush the old one */
  2102.         save_funcs( func, flags, fcond, old_fcond, funchelp);
  2103.         funchelp[0] = EOS;
  2104.     }
  2105.     if (*old_fcond) {
  2106.         SaveEndif(all_funcs);
  2107.         SaveEndif(all__FUNCs);
  2108.         SaveEndif(all__CMDFs);
  2109.     }
  2110.  
  2111.     if (all_names) {
  2112.         nebind = OpenHeader("nebind.h", argv);
  2113.         neexec = OpenHeader("neexec.h", argv);
  2114.         nefunc = OpenHeader("nefunc.h", argv);
  2115.         neprot = OpenHeader("neproto.h", argv);
  2116.         nename = OpenHeader("nename.h", argv);
  2117.         dump_names();
  2118.         dump_bindings();
  2119.         dump_execs(neexec, OPT_EXEC_MACROS);
  2120.         dump_funcs(neprot, all_funcs);
  2121.  
  2122.         Fprintf(nefunc, "\n#ifdef real_CMDFUNCS\n\n");
  2123.         dump_funcs(nefunc, all__FUNCs);
  2124.         Fprintf(nefunc, "\n#else\n\n");
  2125.         dump_funcs(nefunc, all__CMDFs);
  2126.         Fprintf(nefunc, "\n#endif\n");
  2127.     }
  2128.  
  2129.     if (all_envars) {
  2130.         dump_envars();
  2131.         dump_ufuncs();
  2132.         finish_vars_h();
  2133.     }
  2134.  
  2135.     dump_fsms();
  2136.     finish_fsms_h();
  2137.  
  2138.     if (all_wmodes || all_bmodes) {
  2139.         nemode = OpenHeader("nemode.h", argv);
  2140.         DefineOffset(nemode);
  2141.         dump_majors();
  2142.         dump_all_modes();
  2143.         dump_all_submodes();
  2144.         dump_gmodes();
  2145.         dump_mmodes();
  2146.         dump_bmodes();
  2147.         dump_wmodes();
  2148.     }
  2149.  
  2150.     free_mktbls();
  2151.     ReturnFromMain(GOODEXIT);
  2152.     /*NOTREACHED*/
  2153. }
  2154.