|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T a
Length: 7237 (0x1c45) Types: TextFile Names: »args.y«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« └─⟦dcb95597f⟧ └─⟦this⟧ »args.y«
%{ #ifndef lint static char rcsid[] = "$Header: args.y,v 2.4 86/02/08 21:06:25 deboor Exp $"; static char notice[] = "This program is in the public domain and is available for unlimited \ distribution as long as this notice is enclosed."; #endif /* * Argument processor grammar. Called to build argument vector and sequence * when reading a command in non-immediate mode. * * $Source: /c/support/deboor/usr/src/old/vmh/RCS/args.y,v $ * $Revision: 2.4 $ * $Author: deboor $ * */ #include "vmh.h" # define SET_SNG_T(t) single_type[1] = single_type[0]; single_type[0] = t extern CMD thiscomm; jmp_buf ByeBye; /* for error "recovery" */ int unit_sequence[2]; int single_type[2], msg, i; char CommandLine[132]; char *command; %} %union { int num; int *seq; char *str; }; %token NUM SEQ STR MINUS PLUS COLON COLMIN COLPLS UNI DOTDOT %token FIRST LAST PREV NEXT CUR %type <num> single NUM FIRST LAST PREV NEXT CUR %type <seq> range SEQ %type <str> STR %left NUM SEQ STR %left PLUS MINUS DOTDOT %left COLMIN COLPLS %left COLON %left UNI %start argline %% argline : args { CurSequence = readsequence ("_args", F); if (! *CurSequence ) UseSequence = 0; else UseSequence = 1; } ; args : /* could be empty */ | args single { unit_sequence[0] = $2; add_to_sequence ("_args", unit_sequence, F); } | args range { add_to_sequence ("_args", $2, F); free ($2); } | args SEQ { add_to_sequence ("_args", $2, F); free ($2); } | args PLUS STR { thiscomm.c_argv[thiscomm.c_argc++] = $3; } | args STR { thiscomm.c_argv[thiscomm.c_argc++] = $2; } ; range : single MINUS single { /* * this is probably bad style, but it saves code * and makes things a little more readable. since the * values of $1 and $3 are the same for this and * simple_range, we can just goto it and have the * same thing happen. */ goto simple_range; } | single DOTDOT single { simple_range: if ($1 > $3) { i = $3; $3 = $1; $1 = i; } for (i = $1, msg = 0; i <= $3; i++) if (Exists(i, &F->f_msgs)) msg++; $$ = (int *) Calloc (msg+1, sizeof(int)); for (msg = $1, i = 0; msg <= $3; msg++) if (Exists(msg, &F->f_msgs)) $$[i++] = msg; } | single COLON NUM { register incr; /* the increment */ register max_i = $3; /* the upper bound for i */ register ubound; /* the lower bound for msg */ switch (single_type[0]) { case FIRST: case NEXT: incr = 1; ubound = F->f_msgs.m_hghmsg + 1; break; case LAST: case PREV: incr = -1; ubound = F->f_msgs.m_lowmsg - 1; break; case CUR: yyerror ("'cur' not allowed in ':' pair"); YYABORT; default: yyerror ("first part of ':' pair must be a sequence"); YYABORT; } $$ = (int *) Calloc ($3 + 1, sizeof (int)); for (msg = $1, i = 0; i < $3; i++, msg += incr) { while (msg != ubound && ! (Exists(msg,&F->f_msgs))) msg += incr; if (msg == ubound) break; $$[i] = msg; } } | single COLPLS NUM { $$ = (int *) Calloc ($3 + 1, sizeof (int)); for (msg = $1,i = 0; i < $3; i++) { while (msg <= F->f_msgs.m_hghmsg && ! (Exists(msg,&F->f_msgs))) msg++; if (msg > F->f_msgs.m_hghmsg) break; $$[i] == msg; } } | single COLMIN NUM { $$ = (int *) Calloc ($3 + 1, sizeof (int)); for (msg = $1 , i = 0; i < $3; i++) { while (msg >= F->f_msgs.m_lowmsg && ! (Exists(msg,&F->f_msgs))) msg--; if (msg < F->f_msgs.m_lowmsg) break; $$[i] == msg; } } ; single : FIRST { $$ = $1; SET_SNG_T(FIRST); } | LAST { $$ = $1; SET_SNG_T(LAST); } | PREV { $$ = $1; SET_SNG_T(PREV); } | NEXT { $$ = $1; SET_SNG_T(NEXT); } | CUR { $$ = $1; SET_SNG_T(CUR); } | NUM { if (Exists ($1,&F->f_msgs)) { $$ = $1; SET_SNG_T(0); } else { yyerror ("no such message"); /*NOTREACHED*/ } } ; %% yyerror (msg) char *msg; { errormsg (msg, 1); longjmp (ByeBye, 1); } char do_backslash (c) char c; { switch (c) { case 'n': return ('\n'); case 't': return ('\t'); case 'b': return ('\b'); case 'r': return ('\r'); case 'f': return ('\f'); case ERR: return ('\0'); default: return (c); } } #define Getch() (*command=='\n')?'\0':*command++ #define unGetch(c,junk) *--command = c char yytext[1024]; int yyleng; yylex() { char c; /* input character */ int *seq; /* sequence read */ int p_d_num; /* pre-defined sequence number */ yyleng = 0; while (isspace (c = Getch ())) if (c == '\n' || c == '\r') return (0); switch (c) { case '"': while ((c = Getch (cmdWin)) != '"') { if (c == '\\') if ((yytext[yyleng++] = do_backslash (Getch ())) == '\0') break; else if (c == ERR || c == '\n' || c == '\r') yyerror ("Unmatched \""); else yytext[yyleng++] = c; } yytext[yyleng] = '\0'; yylval.str = (char *) Malloc (yyleng+1); (void) strcpy (yylval.str, yytext); return STR; case ':': if ((c = Getch ()) == '+') return COLPLS; else if (c == '-') return COLMIN; else { unGetch (c, stdin); return COLON; } case '+': return PLUS; case '-': return MINUS; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': do { yytext[yyleng++] = c; c = Getch (); } while (isdigit (c)); yytext[yyleng] = '\0'; yylval.num = atoi (yytext); unGetch (c, stdin); if (yylval.num > MAXFOLDER) yyerror ("number too large"); return NUM; case '\0': return (0); case '.': if ((c = Getch ()) == '.') return DOTDOT; else if (c != ERR) { unGetch (c, stdin); c = '.'; } else return (0); case '\'': if (((c = Getch()) >= 'a' && c <= 'z') || c == '\'') { yylval.num = getMark (c); if (! yylval.num) yyerror ("no such mark"); return NUM; } else { unGetch (c, stdin); c = '\''; } /*FALLTHRU*/ default: yytext[yyleng++] = c; while ((c = Getch())!= ERR && (isprint(c) && c != '.' && c != ':') && yyleng < sizeof(yytext)) if (c == '\\') yytext[yyleng++] = do_backslash (Getch()); else yytext[yyleng++] = c; if (yyleng >= sizeof(yytext)) { yyerror ("sequence name too long"); return (0); } unGetch (c, stdin); yytext[yyleng] = '\0'; seq = readsequence (yytext, F); if ((p_d_num = is_pre_def (yytext)) && p_d_num != PD_ALL) { yylval.num = seq[0]; free(seq); switch(p_d_num) { case PD_FIRST: return FIRST; case PD_LAST: return LAST; case PD_NEXT: return NEXT; case PD_PREV: return PREV; case PD_CUR: return CUR; default: punt ("internal error in yylex!!"); } } if (seq == (int *)0) { free(seq); delete_sequence (yytext,F); yylval.str = (char *) Malloc (yyleng+1); (void) strcpy (yylval.str, yytext); return STR; } yylval.seq = seq; return SEQ; } } read_args() { int rc; #ifdef YYDEBUG extern int yydebug; yydebug = 1; #endif thiscomm.c_argc = 0; unit_sequence[0] = 0; set_sequence ("_args", unit_sequence, F); if (setjmp (ByeBye)) return (1); rc = mywgetstr (cmdWin, CommandLine); if (!rc) /* abort */ return (1); command = CommandLine; return (yyparse()); }