home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / listings / v_10_03 / 1003088a < prev    next >
Text File  |  1992-01-13  |  12KB  |  454 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__                        /* ANSI variable-#-of-args method: */
  315.  int warning(char *fmt, ...)
  316.  {
  317.      va_list arglist;
  318.      va_start(arglist, fmt);
  319.  
  320.  #else                                         /* old "varargs" method: */
  321.  int warning(fmt, va_alist)
  322.  char *fmt;
  323.  va_dcl
  324.  {
  325.      va_list arglist;
  326.      va_start(arglist);
  327.  #endif
  328.                               /* the rest is the same, ANSI or varargs: */
  329.  
  330.      fprintf(stderr, "%s (%d): ", src_name, lineno);
  331.      vfprintf(stderr, fmt, arglist);
  332.      va_end(arglist);
  333.      fprintf(stderr, "\n");
  334.      return OK;
  335.  }
  336.  
  337.  
  338.  /************************************************************
  339.   * error():
  340.   *  Display an error message, preceded by source
  341.   *  file name and line number, supporting format
  342.   *  conversions.
  343.   ************************************************************/
  344.  
  345.  #if __STDC__                        /* ANSI variable-#-of-args method: */
  346.  int error(char *fmt, ...)
  347.  {
  348.      va_list arglist;
  349.      va_start(arglist, fmt);
  350.  
  351.  #else                                         /* old "varargs" method: */
  352.  int error(fmt, va_alist)
  353.  char *fmt;
  354.  va_dcl
  355.  {
  356.      va_list arglist;
  357.      va_start(arglist);
  358.  #endif
  359.  
  360.                               /* the rest is the same, ANSI or varargs: */
  361.  
  362.      fprintf(stderr, "%s (%d): ", src_name, lineno);
  363.      vfprintf(stderr, fmt, arglist);
  364.      va_end(arglist);
  365.      fprintf(stderr, "\n");
  366.      err_flag = TRUE;
  367.      return ERROR;
  368.  }
  369.  
  370.  
  371.  /************************************************************
  372.   * fatalerr():
  373.   *  Like error, except global flag "fatal" is set.
  374.   ************************************************************/
  375.  
  376.  #if __STDC__                         /* start function the ANSI way... */
  377.  int fatalerr(char *fmt, ...)
  378.  {
  379.      va_list arglist;
  380.      va_start(arglist, fmt);
  381.  #else                                   /* or the old "varargs" way... */
  382.  int fatalerr(fmt, va_alist)
  383.  char *fmt;
  384.  va_dcl
  385.  {
  386.      va_list arglist;
  387.      va_start(arglist);
  388.  #endif
  389.  
  390.      error(fmt, arglist);          /* the rest is same, ANSI or varargs */
  391.      va_end(arglist);
  392.      fatal = TRUE;
  393.      return ERROR;
  394.  }
  395.  
  396.  
  397.  /************************************************************
  398.   * matchkey(): 
  399.   *  Test if given string is a reserved word. Return the token
  400.   *  value of the matching token if so; else return NULL.
  401.   ************************************************************/
  402.  
  403.  int matchkey(str)
  404.  char *str;
  405.  {
  406.      char str2[MAX_CMD], *cp;
  407.      int i;
  408.      
  409.      strcpy(str2, str);
  410.      for (cp = str2; *cp; cp++)
  411.          *cp = tolower(*cp);
  412.      
  413.      for (i = 0; i < (int) N_KEYWORDS; i++)
  414.          if (!strcmp(keywords[i].keyword, str2))
  415.              return i;
  416.  
  417.      return NULL;
  418.  }
  419.  
  420.  
  421.  #ifdef NEEDSTR
  422.  /*
  423.   * Search for first occurence of substring s2 in s1:
  424.   *  (provided for Xenix only; this function is in
  425.   *   most modern standard distribution libraries)
  426.   */
  427.  
  428.  char *strstr(s1, s2)
  429.  char *s1, *s2;
  430.  {
  431.      int i, j, nposs;
  432.      int len1 = strlen(s1);
  433.  
  434.      int len2 = strlen(s2);
  435.      char *p1;
  436.      
  437.      
  438.      if (len1 < len2)
  439.          return NULL;
  440.          
  441.      nposs = len1 - len2;
  442.      
  443.      for (i = 0; i <= nposs; i++)
  444.      {
  445.          for (j = 0, p1 = &s1[i]; j < len2;  j++)
  446.              if (*p1++ != s2[j])
  447.                  break;
  448.          if (j == len2)
  449.              return &s1[i];
  450.      }               
  451.      return NULL;
  452.  }
  453.  #endif
  454.