|
|
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());
}