home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / mkid2 / part04 / iid.y next >
Text File  |  1991-10-09  |  11KB  |  504 lines

  1. %{
  2. /* This is the yacc definition for the iid command language.
  3.  * The main program, scanner, and parser are defined here.
  4.  * The utility functions invoked from here are in iidfun.c
  5.  */
  6.  
  7. #include "iiddef.h"
  8.  
  9. %}
  10.  
  11. %union {
  12.    set_type *     setdef ;   
  13.    id_type *      strdef ;
  14.    id_list_type * listdef ;
  15. }
  16.  
  17. %token < setdef > SET
  18.  
  19. %token < strdef > ID SHELL_QUERY SHELL_COMMAND
  20.  
  21. %type < setdef > Query Primitive
  22.  
  23. %type < listdef > Lid_group Aid_group Id_list Command_list
  24.  
  25. %token LID AID BEGIN SETS SS FILES SHOW HELP OFF MATCH
  26.  
  27. %left OR
  28.  
  29. %left AND
  30.  
  31. %left NOT
  32.  
  33. %start Command
  34.  
  35. %%
  36.  
  37. Command :
  38.    BEGIN ID
  39.       {
  40.          /* cd to the directory specified as argument, flush sets */
  41.  
  42.          SetDirectory($2) ;
  43.          FlushSets() ;
  44.       }
  45. |  Set_query Query
  46. |  File_query Query
  47.       {
  48.          /* print the list of files resulting from Query */
  49.  
  50.          PrintSet($2) ;
  51.       }
  52. |  SHOW SET
  53.       {
  54.          /* run PAGER on the list of files in SET */
  55.  
  56.          RunPager(Pager, $2) ;
  57.       }
  58. |  SETS
  59.       {
  60.          /* describe sets created so far */
  61.  
  62.          DescribeSets() ;
  63.       }
  64. |  HELP
  65.       {
  66.          /* run PAGER on the help file */
  67.  
  68.          RunPager(Pager, HelpSet) ;
  69.       }
  70. |  OFF
  71.       {
  72.          exit(0) ;
  73.       }
  74. | SHELL_QUERY Command_list
  75.       {
  76.          /* run the shell command and eat the results as a file set */
  77.  
  78.          OneDescription(RunProg($1->id, $2)) ;
  79.          free($1) ;
  80.       }
  81. | SHELL_COMMAND Command_list
  82.       {
  83.          /* run the shell command */
  84.  
  85.          RunShell($1->id, $2) ;
  86.          free($1) ;
  87.       }
  88. ;
  89.  
  90. Set_query :
  91.    SS
  92.       {
  93.          /* Turn on verbose query flag */
  94.  
  95.          VerboseQuery = TRUE ;
  96.       }
  97. ;
  98.  
  99. File_query :
  100.    FILES
  101.       {
  102.          /* Turn off verbose query flag */
  103.  
  104.          VerboseQuery = FALSE ;
  105.       }
  106. ;
  107.  
  108. Query :
  109.    Primitive
  110.       {
  111.          /* value of query is set associated with primitive */
  112.  
  113.          $$ = $1 ;
  114.       }
  115. |  Query AND Query
  116.       {
  117.          /* value of query is intersection of the two query sets */
  118.  
  119.          $$ = SetIntersect($1, $3) ;
  120.          if (VerboseQuery) {
  121.             OneDescription($$) ;
  122.          }
  123.       }
  124. |  Query OR Query
  125.       {
  126.          /* value of query is union of the two query sets */
  127.  
  128.          $$ = SetUnion($1, $3) ;
  129.          if (VerboseQuery) {
  130.             OneDescription($$) ;
  131.          }
  132.       }
  133. |  NOT Query
  134.       {
  135.          /* value of query is inverse of other query */
  136.          
  137.          $$ = SetInverse($2) ;
  138.          if (VerboseQuery) {
  139.             OneDescription($$) ;
  140.          }
  141.       }
  142. ;
  143.  
  144. Primitive :
  145.    SET
  146.       {
  147.          /* Value of primitive is value of recorded set */
  148.  
  149.          $$ = $1 ;
  150.       }
  151. |  Lid_group
  152.       {
  153.          /* Value of primitive is obtained by running an lid query */
  154.  
  155.          $$ = RunProg(LidCommand, $1) ;
  156.          if (VerboseQuery) {
  157.             OneDescription($$) ;
  158.          }
  159.       }
  160. |  Aid_group
  161.       {
  162.          /* Value of primitive is obtained by running an aid query */
  163.  
  164.          $$ = RunProg("aid -kmn", $1) ;
  165.          if (VerboseQuery) {
  166.             OneDescription($$) ;
  167.          }
  168.       }
  169. |  MATCH Id_list
  170.       {
  171.          /* Match names from database against pattern */
  172.          $$ = RunProg("pid -kmn", $2) ;
  173.          if (VerboseQuery) {
  174.             OneDescription($$) ;
  175.          }
  176.       }
  177. |  '(' Query ')'
  178.       {
  179.          /* value of primitive is value of query */
  180.  
  181.          $$ = $2 ;
  182.       }
  183. ;
  184.  
  185. Lid_group :
  186.    ID
  187.       {
  188.          /* make arg list holding single ID */
  189.  
  190.          $$ = InitList() ;
  191.          $$ = ExtendList($$, $1) ;
  192.          LidCommand = DefaultCommand ;
  193.       }
  194. |  LID Id_list
  195.       {
  196.          /* arg list is Id_list */
  197.  
  198.          $$ = $2 ;
  199.          LidCommand = "lid -kmn" ;
  200.       }
  201. ;
  202.  
  203. Aid_group :
  204.    AID Id_list
  205.       {
  206.          /* arg list is Id_list */
  207.  
  208.          $$ = $2 ;
  209.       }
  210. ;
  211.  
  212. Command_list :
  213.    ID
  214.       {
  215.          /* make arg list holding single ID */
  216.  
  217.          $$ = InitList() ;
  218.          $$ = ExtendList($$, $1) ;
  219.       }
  220. |  SET
  221.       {
  222.          /* make arg list holding names from set */
  223.  
  224.          $$ = InitList() ;
  225.          $$ = SetList($$, $1) ;
  226.       }
  227. |  Command_list ID
  228.       {
  229.          /* extend arg list with additional ID */
  230.  
  231.          $$ = ExtendList($1, $2) ;
  232.       }
  233. |  Command_list SET
  234.       {
  235.          /* extend arg list with additional file names */
  236.  
  237.          $$ = SetList($1, $2) ;
  238.       }
  239. ;
  240.  
  241. Id_list :
  242.    ID
  243.       {
  244.          /* make arg list holding single ID */
  245.  
  246.          $$ = InitList() ;
  247.          $$ = ExtendList($$, $1) ;
  248.       }
  249. |  Id_list ID
  250.       {
  251.          /* extend arg list with additional ID */
  252.  
  253.          $$ = ExtendList($1, $2) ;
  254.       }
  255. ;
  256.  
  257. %%
  258.  
  259. /* ScanLine - a global variable holding a pointer to the current
  260.  * command being scanned.
  261.  */
  262. char *             ScanLine ;
  263.  
  264. /* ScanPtr - a global pointer to the current scan position in ScanLine.
  265.  */
  266. char *             ScanPtr ;
  267.  
  268. /* yytext - buffer holding the token.
  269.  */
  270. char               yytext [ MAXCMD ] ;
  271.  
  272. /* yyerror - process syntax errors.
  273.  */
  274. int
  275. yyerror(s)
  276.    char *     s ;
  277. {
  278.    if (*ScanPtr == '\0') {
  279.       fprintf(stderr,"Syntax error near end of command.\n") ;
  280.    } else {
  281.       fprintf(stderr,"Syntax error on or before %s\n",ScanPtr) ;
  282.    }
  283.    return(0) ;
  284. }
  285.  
  286. /* ScanInit - initialize the yylex routine for the new line of input.
  287.  * Basically just initializes the global variables that hold the char
  288.  * ptrs the scanner uses.
  289.  */
  290. void
  291. ScanInit(line)
  292.    char *    line ;
  293. {
  294.    /* skip the leading white space - the yylex routine is sensitive
  295.     * to keywords in the first position on the command line.
  296.     */
  297.    
  298.    while (isspace(*line)) ++line ;
  299.    ScanLine = line ;
  300.    ScanPtr = line ;
  301. }
  302.  
  303. /* NameEq - compare two names for equality in a case insensitive manner.
  304.  * return TRUE for equal, FALSE otherwise.
  305.  */
  306. int
  307. NameEq(n1,n2)
  308.    char *      n1 ;
  309.    char *      n2 ;
  310. {
  311.    char        c1 ;
  312.    char        c2 ;
  313.    
  314.    for ( ; ; ) {
  315.       c1 = *n1++ ;
  316.       c2 = *n2++ ;
  317.       if (isalpha(c1)) c1 = tolower(c1) ;
  318.       if (isalpha(c2)) c2 = tolower(c2) ;
  319.       if (c1 != c2) return FALSE ;
  320.       if (c1 == '\0') return TRUE ;
  321.    }
  322. }
  323.  
  324. /* yylex - the scanner for iid. Basically a kludge ad-hoc piece of junk,
  325.  * but what the heck, if it works...
  326.  *
  327.  * Mostly just scans for non white space strings and returns ID for them.
  328.  * Does check especially for '(' and ')'. Just before returning ID it
  329.  * checks for command names if it is the first token on line or
  330.  * AND, OR, LID, AID if it is in the middle of a line.
  331.  */
  332. int
  333. yylex()
  334. {
  335.    char *      bp ;
  336.    char        c ;
  337.    int         code = ID ;
  338.    char *      dp ;
  339.    char *      sp ;
  340.    int         val ;
  341.    
  342.    bp = ScanPtr ;
  343.    while (isspace(*bp)) ++bp ;
  344.    sp = bp ;
  345.    c = *sp++ ;
  346.    if ((c == '(') || (c == ')') || (c == '\0')) {
  347.       ScanPtr = sp ;
  348.       if (c == '\0') {
  349.          --ScanPtr ;
  350.       }
  351.       return(c) ;
  352.    } else {
  353.       dp = yytext ;
  354.       while (! ((c == '(') || (c == ')') || (c == '\0') || isspace(c))) {
  355.          *dp++ = c ;
  356.          c = *sp++ ;
  357.       }
  358.       *dp++ = '\0' ;
  359.       ScanPtr = sp - 1 ;
  360.       if (bp == ScanLine) {
  361.  
  362.          /* first token on line, check for command names */
  363.  
  364.          if (NameEq(yytext, "SS")) return(SS) ;
  365.          if (NameEq(yytext, "FILES")) return(FILES) ;
  366.          if (NameEq(yytext, "F")) return(FILES) ;
  367.          if (NameEq(yytext, "HELP")) return(HELP) ;
  368.          if (NameEq(yytext, "H")) return(HELP) ;
  369.          if (NameEq(yytext, "?")) return(HELP) ;
  370.          if (NameEq(yytext, "BEGIN")) return(BEGIN) ;
  371.          if (NameEq(yytext, "B")) return(BEGIN) ;
  372.          if (NameEq(yytext, "SETS")) return(SETS) ;
  373.          if (NameEq(yytext, "SHOW")) return(SHOW) ;
  374.          if (NameEq(yytext, "P")) return(SHOW) ;
  375.          if (NameEq(yytext, "OFF")) return(OFF) ;
  376.          if (NameEq(yytext, "Q")) return(OFF) ;
  377.          if (NameEq(yytext, "QUIT")) return(OFF) ;
  378.          if (yytext[0] == '!') {
  379.             code = SHELL_COMMAND ;
  380.          } else {
  381.             code = SHELL_QUERY ;
  382.          }
  383.       } else {
  384.  
  385.          /* not first token, check for operator names */
  386.  
  387.          if (NameEq(yytext, "LID")) return(LID) ;
  388.          if (NameEq(yytext, "AID")) return(AID) ;
  389.          if (NameEq(yytext, "AND")) return(AND) ;
  390.          if (NameEq(yytext, "OR")) return(OR) ;
  391.          if (NameEq(yytext, "NOT")) return(NOT) ;
  392.          if (NameEq(yytext, "MATCH")) return(MATCH) ;
  393.          if ((yytext[0] == 's' || yytext[0] == 'S') && isdigit(yytext[1])) {
  394.             
  395.             /* this might be a set specification */
  396.             
  397.             sp = &yytext[1] ;
  398.             val = 0 ;
  399.             for ( ; ; ) {
  400.                c = *sp++ ;
  401.                if (c == '\0') {
  402.                   if (val < NextSetNum) {
  403.                      yylval.setdef = TheSets[val] ;
  404.                      return(SET) ;
  405.                   }
  406.                }
  407.                if (isdigit(c)) {
  408.                   val = (val * 10) + (c - '0') ;
  409.                } else {
  410.                   break ;
  411.                }
  412.             }
  413.          }
  414.       }
  415.       yylval.strdef = (id_type *)malloc(sizeof(id_type) + strlen(yytext)) ;
  416.       if (yylval.strdef == NULL) {
  417.          fatal("Out of memory in yylex") ;
  418.       }
  419.       yylval.strdef->next_id = NULL ;
  420.       if (code == SHELL_COMMAND) {
  421.          strcpy(yylval.strdef->id, &yytext[1]) ;
  422.       } else {
  423.          strcpy(yylval.strdef->id, yytext) ;
  424.       }
  425.       return(code) ;
  426.    }
  427. }
  428.  
  429. /* The main program for iid - parse the command line, initialize processing,
  430.  * loop processing one command at a time.
  431.  */
  432. main(argc, argv)
  433.    int         argc ;
  434.    char *      argv [ ] ;
  435. {
  436.    int         c ;                     /* current option */
  437.    char *      CmdPtr ;                /* Points to the command string */
  438.    char        Command [ MAXCMD ] ;    /* Buffer for reading commands */
  439.    int         Do1 = FALSE ;           /* TRUE if should only do 1 command */
  440.    int         DoPrompt ;              /* TRUE if should write a prompt */
  441.    int         errors = 0 ;            /* error count */
  442.  
  443.    DoPrompt = isatty(fileno(stdin)) ;
  444.    while ((c = getopt(argc, argv, "Hac:")) != EOF) {
  445.       switch(c) {
  446.       case 'a':
  447.          DefaultCommand = "aid -kmn" ;
  448.          break ;
  449.       case 'c':
  450.          CmdPtr = optarg ;
  451.          Do1 = TRUE ;
  452.          break ;
  453.       case 'H':
  454.          fputs("\
  455. iid: interactive ID database query tool. Call with:\n\
  456.    iid [-a] [-c] [-H]\n\
  457. \n\
  458. -a\tUse the aid as the default query command (not lid).\n\
  459. -c cmd\tExecute the single query cmd and exit.\n\
  460. -H\tPrint this message and exit.\n\
  461. \n\
  462. To get help after starting program type 'help'.\n\
  463. ",stderr) ;
  464.          exit(0) ;
  465.       default:
  466.          ++errors ;
  467.          break ;
  468.       }
  469.    }
  470.    if (argc != optind) {
  471.       fputs("iid: Excess arguments ignored.\n",stderr) ;
  472.       ++errors ;
  473.    }
  474.    if (errors) {
  475.       fputs("run iid -H for help.\n",stderr) ;
  476.       exit(1) ;
  477.    }
  478.  
  479.    /* initialize global data */
  480.  
  481.    InitIid() ;
  482.  
  483.    /* run the parser */
  484.  
  485.    if (Do1) {           
  486.       ScanInit(CmdPtr) ;
  487.       exit(yyparse()) ;
  488.    } else {
  489.       for ( ; ; ) {
  490.          if (DoPrompt) {
  491.             fputs(Prompt, stdout) ;
  492.             fflush(stdout) ;
  493.          }
  494.          gets(Command) ;
  495.          if (feof(stdin)) {
  496.             if (DoPrompt) fputs("\n", stdout) ;
  497.             strcpy(Command, "off") ;
  498.          }
  499.          ScanInit(Command) ;
  500.          errors += yyparse() ;
  501.       }
  502.    }
  503. }
  504.