home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 530b.lha / AMenu_v1.3 / Parse.c < prev    next >
C/C++ Source or Header  |  1991-07-03  |  12KB  |  404 lines

  1. /*********************************************************************\
  2. **                               ________________________________    **
  3. **    A n t h o n y             |________    __    __    ________|   **
  4. **                                       |  |o_|  |o_|  |            **
  5. **            T h y s s e n            __|   __    __   |__          **
  6. **                                  __|   __|  |  |  |__   |__       **
  7. **   `` Dragon Computing ! ''    __|   __|     |  |     |__   |__    **
  8. **                              |_____|        |__|        |_____|   **
  9. **                                                                   **
  10. \*********************************************************************/
  11. /*   Parse the users configuration file to set up the extra workbench
  12. ** menus to execute various commands is various ways.
  13. **                                             (See documentation)
  14. */
  15. #undef DBUG   /* don't debug this unless nessary! */
  16. #include "AMenu.h"
  17. #include "AllocStr.h"        /* allocation/copy macro routines */
  18.  
  19.  
  20.   /* Externs */
  21. extern UBYTE    Color[], TColor[];
  22. extern UWORD    FontWidth;
  23. extern USHORT   ItemStyle;
  24. extern unsigned MenuGap, WBMenus;
  25.  
  26. extern void  Warn(char *);
  27. extern void  StartMenu(), AddTitle(char *), AddSkip();
  28. extern struct ExtMenuItem   *AddItem(char *, char);
  29. extern void  AddMenu(char *, int), AddSubMenu(char *, int);
  30. extern void  EndMenu(), EndSubMenu();
  31. extern BOOL  FinishMenu();
  32.  
  33.  
  34. enum status {        /* Parse structure levels */
  35.   STAT_ENTRY, STAT_MENU, STAT_SUB
  36. };
  37.  
  38.   /* Multi character tokens */
  39. enum {
  40.   EOF = -1, STRING,
  41.   CONSOLE, DIRECTORY, COLOR, TCOLOR, STYLE, COMP, BOX, MENUGAP,
  42.   MENU, SUBMENU, ENDMENU, ENDSUBMENU, COLUMNS, ITEM, TITLE, SKIP,
  43.   RB, RUNBACK, CLI, SCR, SCRIPT, WB,   STK, PRI, CON, DIR,   EndToken
  44. };    /* Note command the modes `RB' to `WB' must be in together */
  45.  
  46.  /* The Arp keyword parsing string - in numeral order of tokens above */
  47. char  *TokenTemplate =
  48.  "CONSOLE,DIRECTORY,COLOR,TCOLOR,STYLE,COMP,BOX,MENUGAP,MENU,SUBMENU,ENDMENU,ENDSUBMENU,COLUMNS,ITEM,TITLE,SKIP,RB,RUNBACK,CLI,SCR,SCRIPT,WB,STK,PRI,CON,DIR";
  49.  
  50.  /* checks on the type of a commands argument */
  51. #define isstring(t) ( (t)<EndToken )       /* is the token any string */
  52. #define isnumber(t) ( isstring(t) && isdigit(*String) )
  53.  
  54.  
  55. #define S_SIZE  80
  56. char    String[S_SIZE], NextChar;   /* string token, char after string */
  57. BPTR    Config;           /* File Handle */
  58.  
  59.  
  60. /*   NOTE :- The Lattice 5.04 library function `isalnum()' is
  61. ** incorrect in that the characters  :;<=>?@ are true (is an
  62. ** alphanumeric character).  The library functions `isdigit()'
  63. ** and `isalpha()' is correct, and thus used instead.
  64. **   The macro isalnum() in "ctype.h" works correctly, but
  65. ** involves the linking of the 256 byte flag buffer `_ctype[]'
  66. ** used by the macros.
  67. */
  68. #define isalnum(c)  (isalpha(c) || isdigit(c))
  69.  
  70.  
  71. /*--------------------------------------*/
  72.  
  73. static int LineNum = 0;      /* Line number in config file - 0 = No Need */
  74.  
  75.    /* return a True on any error given to the user */
  76. #define ReportError(Msg)  { UserReport(Msg); return TRUE; }
  77.  
  78. static void
  79. UserReport(Msg)
  80.   char *Msg;
  81. {
  82.   if( LineNum )
  83.     SPrintf(String, "%s : Line %ld \"%s\"", VERSION, LineNum, Msg);
  84.   else
  85.     SPrintf(String, "%s : \"%s\"", VERSION, Msg);
  86.   Printf("\n%s\n", String);  /* CLI Report */
  87.   Warn(String);              /* WB  Report */
  88. }
  89.  
  90.  
  91. static char
  92. GetC()
  93. {
  94.  char c = EOF;
  95.  Read(Config, &c, 1);
  96.  if( c == '\n' )
  97.    LineNum++;
  98.  return c;
  99. }
  100.  
  101.  
  102. static char
  103. GetToken()
  104. {
  105.   char quote;
  106.   register char tok, *p;
  107.   register int i;
  108.  
  109. retry:
  110.   while(isspace(tok=GetC()));             /* skip extra spaces */
  111.   if( tok == '#' ) {                         /* comment */
  112.     while( (tok=GetC()) != '\n' && tok != EOF ) ;
  113.     goto retry;
  114.   }
  115.   quote = (tok == '"');
  116.   if( !quote && !isalnum(tok) )           /* individual Char */
  117.     return tok;
  118.   if( quote )                             /* remove open quote */
  119.     tok=GetC();
  120.  
  121.     /* scan string token -- while !EOF, space in buffer */
  122.   for( i=0, p=String;
  123.          tok != EOF && i < (S_SIZE-1) && (quote ? tok!='"' : !isspace(tok));
  124.            *p++=tok, i++, tok=GetC()  );
  125.   *p = '\0';
  126.   NextChar = tok;   /* record the next character after String */
  127.     /* Use ARP to sort the keywords from the strings */
  128.   tok = GetKeywordIndex( String, TokenTemplate ) + 1; /* convert token */
  129.   DB( Printf( "%s ", String ); )
  130.   return tok;
  131. }
  132.  
  133.  
  134.  
  135. static BOOL
  136. ParseConfig()
  137. {
  138.   register char       t, Statement;
  139.   struct ExtMenuItem *EItem;
  140.   char                Name[80], CommandChar, *p;
  141.   BOOL                OptionLoop;
  142.   enum status         status = STAT_ENTRY;
  143.   int                 Columns;
  144.  
  145.   LineNum = 1;         /* report config line number on errors */
  146.   DB( Printf("\n"); )
  147.   while ( (Statement=GetToken()) != EOF ) {
  148.     switch( Statement ) {
  149.     case CONSOLE:
  150.       if( !isstring(GetToken()) )
  151.         ReportError("Bad CONSOLE Argument");
  152.       if( M->Console )  FreeStr(M->Console);
  153.       M->Console = AllocStr(String);
  154.       break;
  155.     case DIRECTORY:
  156.       if( !isstring(GetToken()) )
  157.         ReportError("Bad DIRECTORY Argument");
  158.       if( M->Directory )  FreeStr(M->Directory);
  159.       M->Directory = AllocStr(String);
  160.       break;
  161.  
  162.     case COLOR:
  163.       if( !isnumber(GetToken()) )
  164.         ReportError("Bad COLOR Argument 1");
  165.       Color[0] = (UWORD)Atol(String);
  166.       if( !isnumber(GetToken()) )
  167.         ReportError("Bad COLOR Argument 2");
  168.       Color[1] = (UWORD)Atol(String);
  169.       break;
  170.  
  171.     case TCOLOR:
  172.       if( !isnumber(GetToken()) )
  173.         ReportError("Bad TCOLOR Argument 1");
  174.       TColor[0] = (UWORD)Atol(String);
  175.       if( !isnumber(GetToken()) )
  176.         ReportError("Bad TCOLOR Argument 2");
  177.       TColor[1] = (UWORD)Atol(String);
  178.       break;
  179.  
  180.     case STYLE:
  181.       switch( GetToken() ) {
  182.       case COMP: ItemStyle = HIGHCOMP; break;
  183.       case BOX:  ItemStyle = HIGHBOX;  break;
  184.       default:
  185.         ReportError("Bad STYLE Argument");
  186.       }
  187.       break;
  188.  
  189.     case MENUGAP:
  190.       if( !isnumber(GetToken()) )
  191.         ReportError("Bad MENUGAP Argument");
  192.       MenuGap = (UWORD)Atol(String);
  193.       if( MenuGap<1 || MenuGap>50 )
  194.         ReportError("MENUGAP out of range");
  195.       MenuGap *= FontWidth;
  196.       break;
  197.  
  198.     case MENU:
  199.       switch( status ) {  /* fall through switch */
  200.       case STAT_SUB:
  201.         EndSubMenu();
  202.       case STAT_MENU:
  203.         EndMenu();
  204.       }
  205.       status = STAT_MENU;
  206.       Columns = 1;
  207.       if( (t=GetToken() == COLUMNS ) ) {
  208.         if( !isnumber(t=GetToken()) )
  209.           ReportError("Bad COLUMNS Argument");
  210.         Columns = Atol(String);
  211.         t=GetToken();
  212.       }
  213.       if( !isstring(t) )
  214.         ReportError("Missing Menu Name");
  215.       AddMenu( String, Columns );
  216.       break;
  217.  
  218.     case SUBMENU:
  219.       switch( status ) {
  220.       case STAT_ENTRY:
  221.         ReportError("Menu Statement expected");
  222.       case STAT_SUB:
  223.         EndSubMenu();
  224.       }
  225.       status = STAT_SUB;
  226.       Columns = 1;
  227.       if( (t=GetToken() == COLUMNS ) ) {
  228.         if( !isnumber(t=GetToken()) )
  229.           ReportError("Bad COLUMNS Argument");
  230.         Columns = Atol(String);
  231.         t=GetToken();
  232.       }
  233.       if( !isstring(t) )
  234.         ReportError("Missing SubMenu Name");
  235.       AddSubMenu( String, Columns );
  236.       break;
  237.  
  238.     case ENDMENU:
  239.       switch( status ) {
  240.       case STAT_ENTRY:
  241.         ReportError("Menu Statment expected");
  242.       case STAT_SUB:
  243.         EndSubMenu();
  244.       }
  245.       EndMenu();
  246.       status = STAT_ENTRY;
  247.       break;
  248.  
  249.     case ENDSUBMENU:
  250.       if( status != STAT_SUB ) {
  251.         ReportError("SubMenu Statment expected");
  252.       }
  253.       EndSubMenu();
  254.       status = STAT_MENU;
  255.       break;
  256.  
  257.  
  258.     case SKIP:       /* these are pretty simular */
  259.     case TITLE:
  260.     case ITEM:
  261.       switch( status ) {
  262.       case STAT_ENTRY:
  263.         ReportError("Menu Statement expected");
  264.       }
  265.       if( Statement == SKIP ) {     /* if Skip finish up */
  266.         AddSkip();
  267.         break;
  268.       }
  269.       if( !isstring(GetToken()) )
  270.         ReportError("Missing Item/Title Name");
  271.       strcpy(Name, String);
  272.  
  273.       if( Statement == TITLE ) {    /* if Title finish up */
  274.         AddTitle(Name);
  275.         break;
  276.       }
  277.       CommandChar = '\0';
  278.       if( (t=GetToken()) == '<' ) {     /* command char */
  279.         CommandChar = GetC();
  280.         if( GetToken() != '>' )
  281.           ReportError("Missing closing '>'");
  282.         t = GetToken();
  283.       }
  284.       if( t != '|' )
  285.         ReportError("Missing '|' separator");
  286.       DB( Printf("| "); )
  287.       EItem = AddItem(Name, CommandChar);
  288.       if( (t=GetToken()) < RB || t > WB )
  289.         ReportError("Missing Execution Mode");
  290.       EItem->Mode  = Toupper(String[0]);   /* R,C,S,W as appropiate */
  291.       EItem->Stack = DEF_STACK;            /* Default Stack Size */
  292.       EItem->Pri   = 0;                    /* Default Prioity */
  293.       for( OptionLoop=TRUE; OptionLoop; ) {
  294.         switch( t=GetToken() ) {
  295.         case STK:        /* Stack -- All modes */
  296.           if( !isnumber(t=GetToken()) )
  297.             ReportError("Bad STK Argument");
  298.           EItem->Stack = (ULONG)Atol(String);
  299.           if( EItem->Stack < 500 || EItem->Stack > 1000000 )
  300.             ReportError("Bad STACK Size given");
  301.           break;
  302.         case PRI:        /* Prioity -- All modes */
  303.           { BOOL neg;
  304.             if( neg = ( (t=GetToken()) == '-') ) t=GetToken();
  305.             if( !isnumber(t) )
  306.               ReportError("Bad PRI Argument");
  307.             EItem->Pri = (BYTE)Atol(String);
  308.             if(neg) EItem->Pri = -EItem->Pri;
  309.           }
  310.           break;
  311.         case CON:        /* Console -- CLI & SCRIPT only */
  312.           if( EItem->Mode != 'C' && EItem->Mode != 'S' )
  313.             ReportError("`CON' -- CLI or SCRIPT modes only");
  314.           if( !isstring(t=GetToken()) )
  315.             ReportError("Bad CON Argument");
  316.           if( EItem->Console )  FreeStr(M->Console);
  317.           EItem->Console = AllocStr(String);
  318.           break;
  319.         case DIR:        /* Current Directory -- not WB */
  320.           if( EItem->Mode == 'W' )
  321.             ReportError("`DIR' -- not in WB mode");
  322.           if( !isstring(t=GetToken()) )
  323.             ReportError("Bad DIR Argument");
  324.           if( EItem->Directory )  FreeStr(M->Directory);
  325.           EItem->Directory = AllocStr(String);
  326.           break;
  327.         default:
  328.           OptionLoop = FALSE;
  329.           break;
  330.         } /* switch */
  331.       } /* option loop */
  332.  
  333.         /* command */
  334.       if( !isstring(t) )
  335.         ReportError("Bad Command Given");
  336.       EItem->Cmd = AllocStr(String);
  337.  
  338.         /* read arguments */
  339.       t = NextChar;          /* char following command string*/
  340.       while( t != '\n' && t != EOF && isspace(t) )
  341.         t=GetC();            /* skip space */
  342.       p = String;
  343.       while( t != '\n' && t != EOF ) {
  344.         *p++ = t;            /* read in rest of line */
  345.         t = GetC(t);
  346.       }
  347.       *p++ = '\n';    /* make it a proper command line */
  348.       *p = '\0';
  349.       if( EItem->Mode != 'W' && EItem->Mode != 'S' ) /* ignore args? */
  350.         EItem->Args = AllocStr(String);
  351.       break; /* end of ITEM statement */
  352.  
  353.     default:
  354.       ReportError("Keyword Expected");
  355.     }
  356.  
  357.     DB( Printf("-END\n"); )
  358.   } /* While Token */
  359.  
  360.   switch( status ) {
  361.   case STAT_SUB:
  362.     EndSubMenu();
  363.   case STAT_MENU:
  364.     EndMenu();
  365.   }
  366.   LineNum = 0;        /* finished config file - no more syntax errors */
  367.   return FALSE;
  368. }
  369.  
  370.  
  371. BOOL
  372. ParseMenus()
  373.   /* Open and Read the Config File -- return FALSE if no error */
  374. {
  375.   BOOL Error;
  376.  
  377.   if( M->Directory )  FreeStr(M->Directory);
  378.   M->Directory = AllocStr(DEF_DIRECTORY);
  379.   if( M->Console )  FreeStr(M->Console);
  380.   M->Console = AllocStr(DEF_CONSOLE);
  381.  
  382.   StartMenu();
  383.   if( WBMenus != 3 )
  384.     ReportError("Unusual Workbench Menus Found!");
  385.  
  386.   Config = ArpOpen(AMENU_CONFIG, MODE_OLDFILE);
  387.   if( !Config ) {
  388.     Config = ArpOpen(AMENU_CONFIG2, MODE_OLDFILE);  /* closed by Arp */
  389.     if( !Config )
  390.       ReportError("Can't find file");
  391.   }
  392.  
  393.   Error = ParseConfig();
  394.  
  395.   if( !Error && FinishMenu() ) {
  396.     SPrintf(String, "%s : \"%s\"", VERSION,
  397.               "Warning: Menu Overflows WorkBench Screen!");
  398.     Warn(String);       /* Warning - don't abort */
  399.   }
  400.  
  401.   return Error;
  402. }
  403.  
  404.