home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_01 / cmenu.exe / CMENU1.C < prev    next >
Text File  |  1991-10-17  |  10KB  |  447 lines

  1. /************************************************************
  2.  *    Program: CMENU Menu Compiler
  3.  *  Module: cmenu1.c
  4.  *        Menu Compiler:
  5.  *        Main and Utility Functions
  6.  *    Written by: Leor Zolman, 7/91
  7.  ************************************************************/
  8.  
  9. #define    MASTER
  10. #include "cmenu.h"
  11. #include "ccmenu.h"
  12.  
  13. #include <string.h>
  14.  
  15. #if __STDC__
  16. #    include <stdarg.h>
  17. #else
  18. #    include <varargs.h>
  19. #endif
  20.  
  21. int main(argc,argv)
  22. int argc;
  23. char **argv;
  24. {
  25.     register i;
  26.     
  27.     printf("CMENU Menu Compiler v%s\n", VERSION);
  28.     if (argc < 2)
  29.     {
  30.         puts("usage: cmenu <menu-source-file(s)>\n");
  31.         return 0;
  32.     }
  33.     
  34.     for (i = 1; i < argc; i++)
  35.         if (dofile(argv[i]) == ERROR)    /* process source files    */
  36.             return 1;
  37.     return 0;
  38. }
  39.  
  40. /************************************************************
  41.  * dofile():
  42.  *    Process a single .mnu source file
  43.  ************************************************************/
  44.  
  45. int dofile(name)
  46. char *name;
  47. {
  48.     register i;
  49.     char *cp;
  50.     
  51.     if ((cp = strstr(name, ".mnu")) ||
  52.        (cp = strstr(name, ".MNU")))
  53.                 *cp = '\0';
  54.  
  55.     strcpy(src_name, name);
  56.     strcat(src_name, ".mnu");
  57.     strcpy(obj_name, name);
  58.  
  59.     if ((fp = fopen(src_name, "r")) == NULL)
  60.         return fprintf(stderr, "Can't open %s\n", src_name);
  61.     
  62.     n_menus = 0;
  63.     lineno = 1;
  64.     in_menu = FALSE;
  65.     fatal = FALSE;
  66.     
  67.     /*    Main processing loop. Read a token and process it,
  68.      *    until end of file is reached:
  69.      */
  70.  
  71.     while ((token = gettok(fp)) != T_EOF)
  72.     {
  73.         if (!in_menu && token != T_MENU)
  74.         {
  75.             error("Each menu must begin with the Menu keyword");
  76.             break;
  77.         }
  78.         if ((*keywords[token].t_func)() == ERROR)
  79.             if (fatal)    /* If fatal error, exit loop    */
  80.                 break;
  81.     }
  82.     
  83.     fclose(fp);
  84.  
  85.     if (!n_menus)
  86.         return error("No menus defined");
  87.     
  88.     if (in_menu)
  89.     {
  90.         if (n_items)
  91.             itemcheck();
  92.         error("Menu definition missing \"Endmenu\" statement");
  93.     }
  94.  
  95.     for (i = 0; i < n_menus; i++)    /* check for undefined    */
  96.         if (!MInfo[i].Processed)    /* "lmenu" references    */
  97.         {
  98.             printf("Local Menu \"%s\" is undefined.\n",
  99.                     MInfo[i].Name);
  100.             err_flag = TRUE;
  101.         }
  102.     
  103.     if (err_flag)
  104.         return ERROR;
  105.         
  106.     if (write_file() == ERROR)
  107.         return ERROR;
  108.     return OK;
  109. }
  110.  
  111.  
  112. /************************************************************
  113.  * create_menu():
  114.  *    Construct a new menu information structure and
  115.  *    return it (by value).
  116.  *    Set fatal to TRUE if can't create.
  117.  ************************************************************/
  118.  
  119. MINFO create_menu(name)
  120. char *name;
  121. {
  122.     MINFO mi;
  123.  
  124.     if (n_menus == MAX_MENUS)
  125.         fatalerr("Maximum # of menus (%d) exceeded", MAX_MENUS);
  126.     else
  127.     {
  128.         strcpy(mi.Name, name);
  129.         mi.Processed = FALSE;
  130.     }
  131.     return mi;
  132. }
  133.  
  134.  
  135. /************************************************************
  136.  * find_menu():
  137.  *    Search the Menu Info table for a named local menu.
  138.  *    If found:
  139.  *        Return a pointer to the entry if found, and set
  140.  *        global variable menu_num to the menu's index
  141.  *    else:
  142.  *        return NULL
  143.  ************************************************************/
  144.  
  145. MINFO *find_menu(name)
  146. char *name;
  147. {
  148.     int i;
  149.     
  150.     for (i = 0; i < n_menus; i++)
  151.         if (!strcmp(MInfo[i].Name, name))
  152.         {
  153.             menu_num = i;
  154.             return &MInfo[i];
  155.         }
  156.     return NULL;
  157. }
  158.  
  159.  
  160. /************************************************************
  161.  * create_item(): Allocate space for Item Info structure,
  162.  *    Initialize it and return a pointer to the structure
  163.  *    Return NULL if there was a creation error.
  164.  ************************************************************/
  165.  
  166. IINFO *create_item(name)
  167. char *name;
  168. {
  169.     IINFO *IIp;
  170.     ITEM *Ip;
  171.     
  172.     if (n_items == MAX_ITEMS) 
  173.     {
  174.            fatalerr("Max. # of items (%d) exceeded", MAX_ITEMS);
  175.         return NULL;
  176.     }
  177.     
  178.     if ((IIp = (IINFO *) malloc(sizeof(IINFO))) == NULL)
  179.     {
  180.         fatalerr("Out of memory");
  181.         return NULL;
  182.     }
  183.     
  184.     strcpy(IIp->Name, name);
  185.     Ip = &IIp->Item;
  186.     Ip->acttyp = ACT_NONE;
  187.     Ip->pre_clear = Ip->post_clear = Ip->prompt = DEFAULT;
  188.     Ip->nextcode = DEFAULT;
  189.     Ip->nextitem = Ip->lmenunum = 0;
  190.     *Ip->text = *Ip->path = *Ip->action = *Ip->help = '\0';
  191.     return IIp;
  192. }
  193.  
  194.  
  195. /************************************************************
  196.  * find_item():
  197.  *    Search the Item Info table for a named item in the
  198.  *    currently active menu definition.
  199.  *    If item name found:
  200.  *        Set item_num to the index value of the Item,
  201.  *        Return a pointer to the entry
  202.  *    else:
  203.  *        return NULL
  204.  ************************************************************/
  205.  
  206. IINFO *find_item(name)
  207. char *name;
  208. {
  209.     int i;
  210.     
  211.     for (i = 0; i < n_items; i++)
  212.         if (!strcmp(MIp->Items[i]->Name, name))
  213.         {
  214.             item_num = i;
  215.             return MIp->Items[i];
  216.         }
  217.     return NULL;
  218. }
  219.  
  220.  
  221. /************************************************************
  222.  * itemcheck():
  223.  *    Check the currently active item to make sure
  224.  *    both a Text and an Action clause have been
  225.  *    explicitly given.
  226.  ************************************************************/
  227.  
  228. Void itemcheck()
  229. {
  230.     if (!*Ip->text)
  231.         error("No TEXT clause found for current item");
  232.     if (Ip->acttyp == ACT_NONE)
  233.         error("No ACTION clause found for current item");
  234. }
  235.  
  236.  
  237. /************************************************************
  238.  * write_file():
  239.  *        Write menu object file to disk, ready for
  240.  *        execution via rmenu.
  241.  *             Menu object file format:
  242.  *        --------------------------------
  243.  *        <count>            (integer count of # of menus in file)
  244.  *        MENU 1            (MENU structure for 1st Menu)
  245.  *            ITEM 1
  246.  *            ITEM 2
  247.  *            ...
  248.  *            ITEM n_items
  249.  *        MENU 2            (MENU structure for 2nd Menu)
  250.  *            ...
  251.  *        .
  252.  *        .
  253.  *        .
  254.  *        MENU <count>    (MENU structure for final Menu)
  255.  *            ...
  256.  *        --------------------------------
  257.  *
  258.  ************************************************************/
  259.  
  260. int write_file()
  261. {
  262.     int i,j;
  263.  
  264.     strcat(obj_name, ".mnc");
  265.     
  266.     if ((fp = fopen(obj_name, "wb")) == NULL)
  267.     {
  268.         fprintf(stderr, 
  269.             "Cannot open %s for writing.\n", obj_name);
  270.         return ERROR;
  271.     }
  272.     
  273.     if (fwrite((Void *)&n_menus, sizeof n_menus, 1, fp) != 1)
  274.     {
  275.         fprintf(stderr,
  276.             "Error writing menu count to %s\n", obj_name);
  277.         return ERROR;
  278.     }
  279.     
  280.     for (i = 0; i < n_menus; i++)
  281.     {
  282.         Mp = &MInfo[i].Menu;
  283.         if (fwrite((Void *) Mp, sizeof (MENU), 1, fp) != 1)
  284.         {
  285.             fprintf(stderr, 
  286.                 "Error writing to %s\n", obj_name);
  287.             return ERROR;
  288.         }
  289.  
  290.         for (j = 0; j < Mp->nitems; j++)
  291.         {
  292.             if (fwrite((Void *) &MInfo[i].Items[j]->Item,
  293.                     sizeof (ITEM), 1, fp) != 1)
  294.             {
  295.                 fprintf(stderr, 
  296.                     "Error writing to %s\n", obj_name);
  297.                 return ERROR;
  298.             }
  299.             free(MInfo[i].Items[j]);
  300.         }
  301.     }
  302.     printf("Menu object file %s written.\n", obj_name);
  303.     return OK;
  304. }
  305.  
  306.  
  307. /************************************************************
  308.  * warning():
  309.  *    Display a warning message, preceded by source
  310.  *    file name and line number, supporting format
  311.  *    conversions.
  312.  ************************************************************/
  313.  
  314. #if __STDC__
  315.   int warning(char *text, ...)
  316. #else
  317.   int warning(text)
  318.   char *text;
  319. #endif
  320. {
  321.     char **textp = &text;
  322.     fprintf(stderr, "%s (%d): ", src_name, lineno);
  323.     fprintf(stderr, text, *++textp, *++textp);
  324.     fprintf(stderr, "\n");
  325.     return OK;
  326. }
  327.  
  328.  
  329. /************************************************************
  330.  * error():
  331.  *    Display an error message, preceded by source
  332.  *    file name and line number, supporting format
  333.  *    conversions.
  334.  ************************************************************/
  335.  
  336. #if __STDC__    /* ANSI variable-#-of-args method: */
  337. int error(char *fmt, ...)
  338. {
  339.     va_list arglist;
  340.     va_start(arglist, fmt);
  341.  
  342. #else            /* old "varargs" method: */
  343. int error(fmt, va_alist)
  344. char *fmt;
  345. va_dcl
  346. {
  347.     va_list arglist;
  348.     va_start(arglist);
  349. #endif
  350.  
  351.                 /* the rest is the same, ANSI or varargs: */
  352.  
  353.     fprintf(stderr, "%s (%d): ", src_name, lineno);
  354.     vfprintf(stderr, fmt, arglist);
  355.     va_end(arglist);
  356.     fprintf(stderr, "\n");
  357.     err_flag = TRUE;
  358.     return ERROR;
  359. }
  360.  
  361.  
  362. /************************************************************
  363.  * fatalerr():
  364.  *    Like error, except global flag "fatal" is set.
  365.  ************************************************************/
  366.  
  367. #if __STDC__            /* start function the ANSI way... */
  368. int fatalerr(char *fmt, ...)
  369. {
  370.     va_list arglist;
  371.  
  372.     va_start(arglist, fmt);
  373. #else                    /* or the old "varargs" way... */
  374. int fatalerr(fmt, va_alist)
  375. char *fmt;
  376. va_dcl
  377. {
  378.     va_list arglist;
  379.     
  380.     va_start(arglist);
  381. #endif
  382.  
  383.     error(fmt, arglist);    /* the rest is same, ANSI or varargs */
  384.     va_end(arglist);
  385.     fatal = TRUE;
  386.     return ERROR;
  387. }
  388.  
  389.  
  390. /************************************************************
  391.  * matchkey(): 
  392.  *    Test if given string is a reserved word. Return the token
  393.  *    value of the matching token if so; else return NULL.
  394.  ************************************************************/
  395.  
  396. int matchkey(str)
  397. char *str;
  398. {
  399.     char str2[MAX_CMD], *cp;
  400.     int i;
  401.     
  402.     strcpy(str2, str);
  403.     for (cp = str2; *cp; cp++)
  404.         *cp = tolower(*cp);
  405.     
  406.     for (i = 0; i < (int) N_KEYWORDS; i++)
  407.         if (!strcmp(keywords[i].keyword, str2))
  408.             return i;
  409.  
  410.     return NULL;
  411. }
  412.  
  413.  
  414. #ifdef NEEDSTR
  415. /*
  416.  * Search for first occurence of substring s2 in s1:
  417.  *  (provided for Xenix only; this function is in
  418.  *   most modern standard distribution libraries)
  419.  */
  420.  
  421. char *strstr(s1, s2)
  422. char *s1, *s2;
  423. {
  424.     int i, j, nposs;
  425.     int len1 = strlen(s1);
  426.  
  427.     int len2 = strlen(s2);
  428.     char *p1;
  429.     
  430.     
  431.     if (len1 < len2)
  432.         return NULL;
  433.         
  434.     nposs = len1 - len2;
  435.     
  436.     for (i = 0; i <= nposs; i++)
  437.     {
  438.         for (j = 0, p1 = &s1[i]; j < len2;    j++)
  439.             if (*p1++ != s2[j])
  440.                 break;
  441.         if (j == len2)
  442.             return &s1[i];
  443.     }                
  444.     return NULL;
  445. }
  446. #endif
  447.