home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 552.lha / ParM_v3.0 / source.LZH / source / Parse.c < prev    next >
C/C++ Source or Header  |  1991-07-28  |  8KB  |  364 lines

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