DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T a

⟦ddb3be786⟧ TextFile

    Length: 7237 (0x1c45)
    Types: TextFile
    Names: »args.y«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦e7f64e0c0⟧ »EurOpenD3/mail/vmh.tar.Z« 
        └─⟦dcb95597f⟧ 
            └─⟦this⟧ »args.y« 

TextFile

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