home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 465.lha / ParM_v2.5r / Parse.c < prev    next >
C/C++ Source or Header  |  1991-01-05  |  7KB  |  345 lines

  1. /*
  2.  *    Parse.c - Copyright © 1990 by S.R. & P.C.
  3.  *
  4.  *    Created:    16 Jun 1990
  5.  *    Modified:    09 Dec 1990  17:38:26
  6.  *
  7.  *    Make>> make
  8.  */
  9.  
  10. #include "Tokens.h"
  11.  
  12.  
  13. /*****                external functions                    *****/
  14.  
  15. extern void AddMenu(char *);
  16. extern void AddSubMenu(char *);
  17. extern void AddEntry(char *, char *, char *, char *, char, char, long, short);
  18. extern void EndSubMenu(void);
  19. extern void FreeMenus(void);
  20. extern void CleanUp(void);
  21.  
  22.  
  23. /*****                 global functions                    *****/
  24.  
  25. BOOL ParseMenus(void);
  26.  
  27.  
  28. /*****                 global variables                    *****/
  29.  
  30. extern struct Window *Win;
  31. extern struct Menu Menu1;
  32. extern char CurCfg[];
  33. extern char CmdWindow[];
  34. extern char ShellWindow[];
  35. extern char ShellCmd[];
  36. extern char WaitCmd[];
  37. extern char TmpDir[];
  38. extern long DefaultStack;
  39. extern UBYTE menu_pen;
  40. extern char *ReqTitle;
  41.  
  42. /*****                 local variables                    *****/
  43.  
  44. static char *KeyWordTab[] = {
  45.     NULL,
  46.     "ITEM",
  47.     "ARUN",
  48.     "RUN",
  49.     "SHELL",
  50.     "WB",
  51.     "CFG",
  52.     "WIN",
  53.     "PRI",
  54.     "STACK",
  55.     "MENU",
  56.     "SUBMENU",
  57.     "ENDSUBMENU",
  58.     "COLOR",
  59.     "CMDWIN",
  60.     "SHELLWIN",
  61.     "SHELLCMD",
  62.     "WAITCMD",
  63.     "TMPDIR"
  64. };
  65.  
  66. /* status  */
  67.  
  68. #define STAT_BEGIN        0
  69. #define STAT_MENU        1
  70. #define STAT_SUBMENU    2
  71. #define STAT_ITEM        4
  72.  
  73. static char *FileBuffer, *CurrentLine, *NextLine, *Byte, *LastByte;
  74. static short LineNum;
  75. static char tok[200];
  76.  
  77.  
  78. /* add the position of the error to the error message */
  79.  
  80. static void Err(char *msg)
  81. {
  82.     SimpleRequest(ReqTitle, "%s\nLine %d, Char %ld", msg, LineNum, Byte-CurrentLine+1);
  83. }
  84.  
  85. #define SYNTAX(msg) { Err(msg); return FALSE; }
  86.  
  87.  
  88. static BOOL get_line(void)
  89. {
  90.     register char *s,c;
  91.  
  92.     s = CurrentLine = NextLine;
  93.     if (!*s)
  94.         return FALSE;
  95.     while ((c = *s++) != 10 && c);
  96.     if (c)
  97.         *(s-1) = '\0';
  98.     NextLine = s;
  99.     LineNum++;
  100.     Byte = CurrentLine;
  101.     return TRUE;
  102. }
  103.  
  104.  
  105. /*
  106.  *    b is a register variable used to replace global Byte pointer in
  107.  *    get_token() body. Then, Byte must be restored before leaving.
  108.  */
  109.  
  110. static char get_token(void)
  111. {
  112.     register char *p, *b, c;
  113.     short i;
  114.     char quote;
  115.  
  116.     b = Byte;
  117.     while ((c = *b) == ' ' || c == '\t')
  118.         b++;            /* skip extra spaces */
  119.     if (c == '#')        /* comment */
  120.         return 0;
  121.     LastByte = b;        /* save address of next token */
  122.     if (c < 32 || c == '{' || c == '}') {
  123.         Byte = (c) ? b+1 : b;    /* prevent skipping of sentinel */
  124.         return c;                /* '{', '}', '\0', or invalid char */
  125.     }
  126.     /* scan string */
  127.     p = tok;
  128.     if (c == '"') {
  129.         b++;
  130.         quote = TRUE;
  131.     }
  132.     else
  133.         quote = FALSE;
  134.     while ((quote && *b != '"' && *b) || (!quote && *b > 32 && *b != ';'))
  135.         *p++ = *b++;
  136.     *p = '\0';
  137.     if (quote)
  138.         b++;    /* skip closing '"' */
  139.     for (i = 1; i <= MAX_KEYWORD; i++) {
  140.         if (!Strcmp(tok, KeyWordTab[i]))
  141.             break;    /* arp Strcmp() is not case sensitive */
  142.     }
  143.     Byte = b;
  144.     return i;
  145. }
  146.  
  147.  
  148. /*
  149.  *    Parse a line that may contain semicolons. Backslash ('\') is the override
  150.  *    char. This function is called from ParseConfig() and from Command().
  151.  */
  152.  
  153. void ParseLine(char *cmd)
  154. {
  155.     register char *s,*d,c;
  156.  
  157.     s = d = cmd;
  158.     while (c = *d++ = *s++) {
  159.         if (c == '\\')
  160.             *(d-1) = *s++;
  161.         else if (c == ';')
  162.             *(d-1) = '\n';
  163.     }
  164. }
  165.  
  166.  
  167. static BOOL ParseConfig(void)
  168. {
  169.     char t, shortcut, mode;
  170.     long stack;
  171.     short pri;
  172.     USHORT status = STAT_BEGIN;
  173.     char *args, *cmd, *win;
  174.     char itemstr[80], cmdstr[100], winstr[80];
  175.  
  176.     FreeMenus();
  177.     while( get_line() ) {
  178.         switch (t = get_token()) {
  179.         case TOK_MENU:
  180.             if (!(status & (STAT_MENU | STAT_ITEM)) && status != STAT_BEGIN)
  181.                 SYNTAX("Unexpected MENU")
  182.             status = STAT_MENU;
  183.             if (get_token())
  184.                 AddMenu(tok);
  185.             else
  186.                 SYNTAX("Unexpected end of line");
  187.             break;
  188.         case TOK_SUBMENU:
  189.             if (!(status & STAT_MENU) || (status & STAT_SUBMENU))
  190.                 SYNTAX("Unexpected SUBMENU")
  191.             status = STAT_SUBMENU;
  192.             if (get_token())
  193.                 AddSubMenu(tok);
  194.             else
  195.                 SYNTAX("Unexpected end of line");
  196.             break;
  197.         case TOK_ENDSUBMENU:
  198.             if (!(status & STAT_SUBMENU) || !(status & STAT_ITEM))
  199.                 SYNTAX("Unexpected ENDSUBMENU")
  200.             EndSubMenu();
  201.             status = STAT_MENU | STAT_ITEM;
  202.             break;
  203.         case TOK_ITEM:
  204.             if (status == STAT_BEGIN)
  205.                 SYNTAX("Unexpected ITEM")
  206.             status |= STAT_ITEM;
  207.             shortcut = pri = 0;
  208.             stack = DefaultStack;
  209.             win = args = NULL;
  210.             cmd = cmdstr;
  211.             if (get_token() == '{') {    /* command char */
  212.                 shortcut = *Byte++;
  213.                 if (get_token() != '}')
  214.                     SYNTAX("Missing closing '}'");
  215.                 get_token();
  216.             }
  217.             strcpy(itemstr, tok);
  218.             switch (mode = get_token()) {
  219.             case TOK_WB:
  220.                 stack = 0;    /* Tell WBRun to take icon stack as default */
  221.             case TOK_SHELL:
  222.             case TOK_ARUN:
  223.             case TOK_RUN:
  224.                 while ((t = get_token())==TOK_WIN || t==TOK_STACK || t==TOK_PRI) {
  225.                     if (!get_token())
  226.                         SYNTAX("Unexpected end of line");
  227.                     switch (t) {
  228.                     case TOK_WIN:
  229.                         if (mode == TOK_RUN || mode == TOK_WB)
  230.                             SYNTAX("WIN not allowed in this mode")
  231.                         strcpy(winstr, tok);
  232.                         win = winstr;
  233.                         break;
  234.                     case TOK_STACK:
  235.                         stack = Atol(tok);
  236.                         if (IoErr() || stack < 2000)
  237.                             SYNTAX("Invalid stack")
  238.                         break;
  239.                     case TOK_PRI:
  240.                         pri = Atol(tok);
  241.                         if (IoErr() || pri < -128 || pri > 127)
  242.                             SYNTAX("Priority out of range")
  243.                         break;
  244.                     }
  245.                 }
  246.                 if (!t)
  247.                     SYNTAX("Unexpected end of line");
  248.                 switch(mode) {
  249.                 case TOK_ARUN:
  250.                     args = Byte;
  251.                 case TOK_WB:
  252.                     strcpy(cmdstr, tok);
  253.                     break;
  254.                 case TOK_SHELL:
  255.                     ParseLine(LastByte);
  256.                 default:    /* RUN mode */
  257.                     cmd = LastByte;
  258.                 }
  259.                 break;
  260.             case TOK_CFG:
  261.                 if (!get_token())
  262.                     SYNTAX("Unexpected end of line");
  263.                 strcpy(cmdstr, tok);
  264.                 break;
  265.             default:
  266.                 Err("WB, ARUN, RUN, SHELL or CFG Expected");
  267.                 return FALSE;
  268.             }
  269.             AddEntry(itemstr, cmd, args, win, shortcut, mode, stack, pri);
  270.             break;
  271.         case TOK_COLOR:
  272.             get_token();
  273.             menu_pen = ((menu_pen = Atol(tok)) == Win->BlockPen) ? Win->DetailPen : menu_pen;    /* control if blockpen and detailpen are different */
  274.             break;
  275.         case TOK_CMDWIN:
  276.             if (get_token())
  277.                 strcpy(CmdWindow, tok);
  278.             break;
  279.         case TOK_SHELLWIN:
  280.             if (get_token())
  281.                 strcpy(ShellWindow, tok);
  282.             break;
  283.         case TOK_SHELLCMD:
  284.             if (get_token())
  285.                 strcpy(ShellCmd, tok);
  286.             break;
  287.         case TOK_WAITCMD:
  288.             if (get_token())
  289.                 strcpy(WaitCmd, tok);
  290.             break;
  291.         case TOK_TMPDIR:
  292.             if (get_token())
  293.                 strcpy(TmpDir, tok);
  294.             break;
  295.         default:
  296.             if (t)    /* allow empty lines */
  297.                 SYNTAX("Keyword expected")
  298.         }
  299.     }
  300.     return TRUE;
  301. }
  302.  
  303.  
  304. BOOL ParseMenus(void)
  305. {
  306.     BPTR lock, cfg;
  307.     struct FileInfoBlock *fib;
  308.     long bufsize, nch;
  309.     BOOL stat;
  310.     BOOL pb = TRUE;
  311.  
  312.     if (!(lock = Lock(CurCfg, ACCESS_READ))) {
  313.         SimpleRequest(ReqTitle,"Can't open '%s'",CurCfg);
  314.         return FALSE;
  315.     }
  316.     if (fib = (struct FileInfoBlock *)
  317.         AllocMem(sizeof(struct FileInfoBlock), MEMF_PUBLIC|MEMF_CLEAR)) {
  318.         if (Examine(lock, (BPTR)fib)) {
  319.             if (fib->fib_DirEntryType < 0) {
  320.                 bufsize = fib->fib_Size + 2;
  321.                 if (FileBuffer = AllocMem(bufsize, MEMF_PUBLIC|MEMF_CLEAR)) {
  322.                     cfg = Open(CurCfg, MODE_OLDFILE);
  323.                     nch = Read(cfg, FileBuffer, bufsize-1);
  324.                     Close(cfg);
  325.                     if (nch == fib->fib_Size) {
  326.                         NextLine = FileBuffer;
  327.                         LineNum = 0;
  328.                         stat = ParseConfig();
  329.                         CleanUp();    /* setup items width */
  330.                         pb = FALSE;
  331.                     }
  332.                     FreeMem(FileBuffer, bufsize);
  333.                 }
  334.             }
  335.         }
  336.         FreeMem(fib, sizeof(struct FileInfoBlock));
  337.     }
  338.     UnLock(lock);
  339.     if (pb) {
  340.         SimpleRequest(ReqTitle, "Error reading '%s'", CurCfg);
  341.         return FALSE;
  342.     }
  343.     return stat;
  344. }
  345.