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