home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume24
/
mkid2
/
part04
/
iid.y
next >
Wrap
Text File
|
1991-10-09
|
11KB
|
504 lines
%{
/* This is the yacc definition for the iid command language.
* The main program, scanner, and parser are defined here.
* The utility functions invoked from here are in iidfun.c
*/
#include "iiddef.h"
%}
%union {
set_type * setdef ;
id_type * strdef ;
id_list_type * listdef ;
}
%token < setdef > SET
%token < strdef > ID SHELL_QUERY SHELL_COMMAND
%type < setdef > Query Primitive
%type < listdef > Lid_group Aid_group Id_list Command_list
%token LID AID BEGIN SETS SS FILES SHOW HELP OFF MATCH
%left OR
%left AND
%left NOT
%start Command
%%
Command :
BEGIN ID
{
/* cd to the directory specified as argument, flush sets */
SetDirectory($2) ;
FlushSets() ;
}
| Set_query Query
| File_query Query
{
/* print the list of files resulting from Query */
PrintSet($2) ;
}
| SHOW SET
{
/* run PAGER on the list of files in SET */
RunPager(Pager, $2) ;
}
| SETS
{
/* describe sets created so far */
DescribeSets() ;
}
| HELP
{
/* run PAGER on the help file */
RunPager(Pager, HelpSet) ;
}
| OFF
{
exit(0) ;
}
| SHELL_QUERY Command_list
{
/* run the shell command and eat the results as a file set */
OneDescription(RunProg($1->id, $2)) ;
free($1) ;
}
| SHELL_COMMAND Command_list
{
/* run the shell command */
RunShell($1->id, $2) ;
free($1) ;
}
;
Set_query :
SS
{
/* Turn on verbose query flag */
VerboseQuery = TRUE ;
}
;
File_query :
FILES
{
/* Turn off verbose query flag */
VerboseQuery = FALSE ;
}
;
Query :
Primitive
{
/* value of query is set associated with primitive */
$$ = $1 ;
}
| Query AND Query
{
/* value of query is intersection of the two query sets */
$$ = SetIntersect($1, $3) ;
if (VerboseQuery) {
OneDescription($$) ;
}
}
| Query OR Query
{
/* value of query is union of the two query sets */
$$ = SetUnion($1, $3) ;
if (VerboseQuery) {
OneDescription($$) ;
}
}
| NOT Query
{
/* value of query is inverse of other query */
$$ = SetInverse($2) ;
if (VerboseQuery) {
OneDescription($$) ;
}
}
;
Primitive :
SET
{
/* Value of primitive is value of recorded set */
$$ = $1 ;
}
| Lid_group
{
/* Value of primitive is obtained by running an lid query */
$$ = RunProg(LidCommand, $1) ;
if (VerboseQuery) {
OneDescription($$) ;
}
}
| Aid_group
{
/* Value of primitive is obtained by running an aid query */
$$ = RunProg("aid -kmn", $1) ;
if (VerboseQuery) {
OneDescription($$) ;
}
}
| MATCH Id_list
{
/* Match names from database against pattern */
$$ = RunProg("pid -kmn", $2) ;
if (VerboseQuery) {
OneDescription($$) ;
}
}
| '(' Query ')'
{
/* value of primitive is value of query */
$$ = $2 ;
}
;
Lid_group :
ID
{
/* make arg list holding single ID */
$$ = InitList() ;
$$ = ExtendList($$, $1) ;
LidCommand = DefaultCommand ;
}
| LID Id_list
{
/* arg list is Id_list */
$$ = $2 ;
LidCommand = "lid -kmn" ;
}
;
Aid_group :
AID Id_list
{
/* arg list is Id_list */
$$ = $2 ;
}
;
Command_list :
ID
{
/* make arg list holding single ID */
$$ = InitList() ;
$$ = ExtendList($$, $1) ;
}
| SET
{
/* make arg list holding names from set */
$$ = InitList() ;
$$ = SetList($$, $1) ;
}
| Command_list ID
{
/* extend arg list with additional ID */
$$ = ExtendList($1, $2) ;
}
| Command_list SET
{
/* extend arg list with additional file names */
$$ = SetList($1, $2) ;
}
;
Id_list :
ID
{
/* make arg list holding single ID */
$$ = InitList() ;
$$ = ExtendList($$, $1) ;
}
| Id_list ID
{
/* extend arg list with additional ID */
$$ = ExtendList($1, $2) ;
}
;
%%
/* ScanLine - a global variable holding a pointer to the current
* command being scanned.
*/
char * ScanLine ;
/* ScanPtr - a global pointer to the current scan position in ScanLine.
*/
char * ScanPtr ;
/* yytext - buffer holding the token.
*/
char yytext [ MAXCMD ] ;
/* yyerror - process syntax errors.
*/
int
yyerror(s)
char * s ;
{
if (*ScanPtr == '\0') {
fprintf(stderr,"Syntax error near end of command.\n") ;
} else {
fprintf(stderr,"Syntax error on or before %s\n",ScanPtr) ;
}
return(0) ;
}
/* ScanInit - initialize the yylex routine for the new line of input.
* Basically just initializes the global variables that hold the char
* ptrs the scanner uses.
*/
void
ScanInit(line)
char * line ;
{
/* skip the leading white space - the yylex routine is sensitive
* to keywords in the first position on the command line.
*/
while (isspace(*line)) ++line ;
ScanLine = line ;
ScanPtr = line ;
}
/* NameEq - compare two names for equality in a case insensitive manner.
* return TRUE for equal, FALSE otherwise.
*/
int
NameEq(n1,n2)
char * n1 ;
char * n2 ;
{
char c1 ;
char c2 ;
for ( ; ; ) {
c1 = *n1++ ;
c2 = *n2++ ;
if (isalpha(c1)) c1 = tolower(c1) ;
if (isalpha(c2)) c2 = tolower(c2) ;
if (c1 != c2) return FALSE ;
if (c1 == '\0') return TRUE ;
}
}
/* yylex - the scanner for iid. Basically a kludge ad-hoc piece of junk,
* but what the heck, if it works...
*
* Mostly just scans for non white space strings and returns ID for them.
* Does check especially for '(' and ')'. Just before returning ID it
* checks for command names if it is the first token on line or
* AND, OR, LID, AID if it is in the middle of a line.
*/
int
yylex()
{
char * bp ;
char c ;
int code = ID ;
char * dp ;
char * sp ;
int val ;
bp = ScanPtr ;
while (isspace(*bp)) ++bp ;
sp = bp ;
c = *sp++ ;
if ((c == '(') || (c == ')') || (c == '\0')) {
ScanPtr = sp ;
if (c == '\0') {
--ScanPtr ;
}
return(c) ;
} else {
dp = yytext ;
while (! ((c == '(') || (c == ')') || (c == '\0') || isspace(c))) {
*dp++ = c ;
c = *sp++ ;
}
*dp++ = '\0' ;
ScanPtr = sp - 1 ;
if (bp == ScanLine) {
/* first token on line, check for command names */
if (NameEq(yytext, "SS")) return(SS) ;
if (NameEq(yytext, "FILES")) return(FILES) ;
if (NameEq(yytext, "F")) return(FILES) ;
if (NameEq(yytext, "HELP")) return(HELP) ;
if (NameEq(yytext, "H")) return(HELP) ;
if (NameEq(yytext, "?")) return(HELP) ;
if (NameEq(yytext, "BEGIN")) return(BEGIN) ;
if (NameEq(yytext, "B")) return(BEGIN) ;
if (NameEq(yytext, "SETS")) return(SETS) ;
if (NameEq(yytext, "SHOW")) return(SHOW) ;
if (NameEq(yytext, "P")) return(SHOW) ;
if (NameEq(yytext, "OFF")) return(OFF) ;
if (NameEq(yytext, "Q")) return(OFF) ;
if (NameEq(yytext, "QUIT")) return(OFF) ;
if (yytext[0] == '!') {
code = SHELL_COMMAND ;
} else {
code = SHELL_QUERY ;
}
} else {
/* not first token, check for operator names */
if (NameEq(yytext, "LID")) return(LID) ;
if (NameEq(yytext, "AID")) return(AID) ;
if (NameEq(yytext, "AND")) return(AND) ;
if (NameEq(yytext, "OR")) return(OR) ;
if (NameEq(yytext, "NOT")) return(NOT) ;
if (NameEq(yytext, "MATCH")) return(MATCH) ;
if ((yytext[0] == 's' || yytext[0] == 'S') && isdigit(yytext[1])) {
/* this might be a set specification */
sp = &yytext[1] ;
val = 0 ;
for ( ; ; ) {
c = *sp++ ;
if (c == '\0') {
if (val < NextSetNum) {
yylval.setdef = TheSets[val] ;
return(SET) ;
}
}
if (isdigit(c)) {
val = (val * 10) + (c - '0') ;
} else {
break ;
}
}
}
}
yylval.strdef = (id_type *)malloc(sizeof(id_type) + strlen(yytext)) ;
if (yylval.strdef == NULL) {
fatal("Out of memory in yylex") ;
}
yylval.strdef->next_id = NULL ;
if (code == SHELL_COMMAND) {
strcpy(yylval.strdef->id, &yytext[1]) ;
} else {
strcpy(yylval.strdef->id, yytext) ;
}
return(code) ;
}
}
/* The main program for iid - parse the command line, initialize processing,
* loop processing one command at a time.
*/
main(argc, argv)
int argc ;
char * argv [ ] ;
{
int c ; /* current option */
char * CmdPtr ; /* Points to the command string */
char Command [ MAXCMD ] ; /* Buffer for reading commands */
int Do1 = FALSE ; /* TRUE if should only do 1 command */
int DoPrompt ; /* TRUE if should write a prompt */
int errors = 0 ; /* error count */
DoPrompt = isatty(fileno(stdin)) ;
while ((c = getopt(argc, argv, "Hac:")) != EOF) {
switch(c) {
case 'a':
DefaultCommand = "aid -kmn" ;
break ;
case 'c':
CmdPtr = optarg ;
Do1 = TRUE ;
break ;
case 'H':
fputs("\
iid: interactive ID database query tool. Call with:\n\
iid [-a] [-c] [-H]\n\
\n\
-a\tUse the aid as the default query command (not lid).\n\
-c cmd\tExecute the single query cmd and exit.\n\
-H\tPrint this message and exit.\n\
\n\
To get help after starting program type 'help'.\n\
",stderr) ;
exit(0) ;
default:
++errors ;
break ;
}
}
if (argc != optind) {
fputs("iid: Excess arguments ignored.\n",stderr) ;
++errors ;
}
if (errors) {
fputs("run iid -H for help.\n",stderr) ;
exit(1) ;
}
/* initialize global data */
InitIid() ;
/* run the parser */
if (Do1) {
ScanInit(CmdPtr) ;
exit(yyparse()) ;
} else {
for ( ; ; ) {
if (DoPrompt) {
fputs(Prompt, stdout) ;
fflush(stdout) ;
}
gets(Command) ;
if (feof(stdin)) {
if (DoPrompt) fputs("\n", stdout) ;
strcpy(Command, "off") ;
}
ScanInit(Command) ;
errors += yyparse() ;
}
}
}