# define INTEGER 257
# define NREF 258
# define PREF 259
# define FIRST 260
# define LAST 261
# define NEXT 262
# define PREV 263
# define FREF 264
# define LREF 265
# define CUR 266
# define NEW 267
# define ALL 268
# define AREF 269

# line 4 "trn_expr.y"
#include <ctype.h>
#include <discuss/discuss.h>
#include "globals.h"

static trn_info *trnexpr_curtrn;
static mtg_info *trnexpr_curmtg;
static int trnexpr_low, trnexpr_high;
static int trnexpr_aref;
static char *cp;
static int trnexpr_err;
#define yyclearin yychar = -1
#define yyerrok yyerrflag = 0
extern int yychar;
extern short yyerrflag;
#ifndef YYMAXDEPTH
#define YYMAXDEPTH 150
#endif
#ifndef YYSTYPE
#define YYSTYPE int
#endif
YYSTYPE yylval, yyval;
# define YYERRCODE 256

# line 62 "trn_expr.y"


/*
 *
 *	Copyright (C) 1989 by the Massachusetts Institute of Technology
 *    	Developed by the MIT Student Information Processing Board (SIPB).
 *    	For copying information, see the file mit-copyright.h in this release.
 *
 */

static yyerror(msg)
	char *msg;
{
#ifdef	lint
	msg = msg;
#endif	lint
	trnexpr_err = DISC_INVALID_TRN_SPECS;
}

/*
 *
 * see if second string is beginning of first string, except for case
 * differences..
 *
 */

#define	to_lower(c)	(((c)<'_')?((c)+'a'-'A'):(c))
static match(s1, s2)
	register char *s1, *s2;
{
	while (*s2) {
		if (to_lower(*s1) != *s2)
			return(0);
		s1++; s2++;
	}
	return(1);
}

static yylex()
{
	if (!*cp) return -1;
	if(isdigit(*cp)) {
		yylval=0;
		do {
			yylval = *(cp++) - '0' + yylval*10;
		} while (*cp && isdigit(*cp));
		return( INTEGER );
	} else if (*cp=='.') {
		cp++;
		yylval=trnexpr_curtrn->current;
		return(CUR);
	} else if (*cp==':' || *cp=='+' || *cp=='-') {
		return(*cp++);
	} else if (match(cp, "current")) {
	        cp += 7;
	        yylval=trnexpr_curtrn->current;
		return(CUR);
	} else if (match(cp, "new")) {
	        cp += 3;
		return(NEW);
	} else if (match(cp, "all")) {
	        cp += 3;
		return(ALL);
	} else if (match(cp, "aref")) {
		cp += 4;
		return(AREF);
	} else if (match(cp, "next")) {
		cp += 4;
		yylval=trnexpr_curtrn->next;
		return(NEXT);
	} else if (match(cp, "prev")) {
		cp += 4;
		yylval=trnexpr_curtrn->prev;
		return(PREV);
 	} else if (match(cp, "nref")) {
		cp += 4;
		yylval=trnexpr_curtrn->nref;
		return(NREF);
	} else if (match(cp, "pref")) {
		cp += 4;
		yylval=trnexpr_curtrn->pref;
		return(PREF);
 	} else if (match(cp, "first")) {
		cp += 5;
		yylval=trnexpr_curmtg->first;
		return(FIRST);
	} else if (match(cp, "last")) {
		cp += 4;
		yylval=trnexpr_curmtg->last;
		return(LAST);
	} else if (match(cp, "fref")) {
		cp += 4;
		yylval=trnexpr_curtrn->fref;
		return(FREF);
	} else if (match(cp, "lref")) {
		cp += 4;
		yylval=trnexpr_curtrn->lref;
		return(LREF);
	} else if (*cp=='n' || *cp=='N') {
		cp++;
		yylval=trnexpr_curtrn->next;
		return(NEXT);
	} else if (*cp=='p' || *cp=='P') {
		cp++;
		yylval=trnexpr_curtrn->prev;
		return(PREV);
  	} else if (*cp=='l' || *cp=='L') {
		cp++;
		yylval=trnexpr_curmtg->last;
		return(LAST);
 	} else if (*cp=='f' || *cp == 'F') {
		cp++;
		yylval=trnexpr_curmtg->first;
		return(FIRST);
	} else return (*cp++);
}

int trnexpr_parse(mtg, trn, string, lorange, highrange, flags)
        mtg_info *mtg;
  	trn_info *trn;
	char *string;
	int *lorange, *highrange, *flags;
{
	cp = string;
	trnexpr_curmtg = mtg;
	trnexpr_curtrn = trn;
	trnexpr_aref = 0;
	trnexpr_err = 0;
	(void) yyparse();
	if(lorange)
		*lorange = trnexpr_low;
	if(highrange)
		*highrange = trnexpr_high;
	if(flags)
		*flags = (trnexpr_aref) ? flag_AREF : 0;
	return(trnexpr_err);
}

#ifdef notdef
mtg_info mtg = { 0, "/tmp/foo", "bar", "quux", 1, 30, 22, 23, 1 };
trn_info trn = { 0, 7, 6, 8, 5, 9, 2, 17, 3, 42, 7, 48, "Qux", "me" };
main(argc, argv)
	int argc;
	char **argv;
{
	int low, high;
	argv++; argc--;
	while(argc--) {
		low = -1; high = -1;
		trnexpr_parse(&mtg, &trn, *argv, &low, &high);
		printf("%s: %d:%d\n", *argv, low, high);
		if(trnexpr_err) {
			printf("Error %d\n", trnexpr_err);
			trnexpr_err=0;
		}
		argv++;
	}
}
#endif notdef
short yyexca[] ={
-1, 1,
	0, -1,
	-2, 0,
	};
# define YYNPROD 21
# define YYLAST 48
short yyact[]={

   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,
   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,
  13,  14,  15,  19,  21,  18,  19,   2,  18,  16,
  17,   1,   0,   0,   0,   0,   0,   0,  20,   0,
   0,   0,   0,   0,   0,  22,  23,  24 };
short yypact[]={

-257,-1000, -20,-1000,-1000,-1000,-1000,-1000,-1000,-1000,
-1000,-1000,-1000,-1000,-1000,-1000,-1000,-244,-244,-244,
-1000,-1000, -17,-1000,-1000 };
short yypgo[]={

   0,  31,  27,  30,  29 };
short yyr1[]={

   0,   1,   1,   1,   1,   1,   3,   3,   2,   2,
   2,   2,   2,   2,   2,   2,   2,   2,   2,   4,
   4 };
short yyr2[]={

   0,   1,   3,   1,   1,   1,   1,   1,   1,   1,
   1,   1,   1,   1,   1,   1,   1,   1,   1,   3,
   3 };
short yychk[]={

-1000,  -1,  -2, 267, 268, 269, 257, 258, 259, 260,
 261, 262, 263, 264, 265, 266,  -4,  -3,  45,  43,
  58,  44,  -2,  -2,  -2 };
short yydef[]={

   0,  -2,   1,   3,   4,   5,   8,   9,  10,  11,
  12,  13,  14,  15,  16,  17,  18,   0,   0,   0,
   6,   7,   2,  19,  20 };
/*
 *	$Source: /afs/rel-eng.athena.mit.edu/project/release/current/source/bsd-4.3/common/usr.bin/yacc/RCS/yaccpar,v $
 *	$Author: epeisach $
 *	$Locker:  $
 *	$Header: /afs/rel-eng.athena.mit.edu/project/release/current/source/bsd-4.3/common/usr.bin/yacc/RCS/yaccpar,v 1.4 90/03/30 10:09:19 epeisach Exp $
 */

#ifndef lint
static char yaccpar_sccsid[] = "@(#)yaccpar	4.1	(Berkeley)	2/11/83";
#endif /* not lint */

# define YYFLAG -1000
# define YYERROR goto yyerrlab
# define YYACCEPT return(0)
# define YYABORT return(1)

/*	parser for yacc output	*/

#ifdef YYDEBUG
int yydebug = 0; /* 1 for debugging */
#endif
YYSTYPE yyv[YYMAXDEPTH]; /* where the values are stored */
int yychar = -1; /* current input token number */
int yynerrs = 0;  /* number of errors */
short yyerrflag = 0;  /* error recovery flag */

yyparse() {

	short yys[YYMAXDEPTH];
	short yyj, yym;
	register YYSTYPE *yypvt;
	register short yystate, *yyps, yyn;
	register YYSTYPE *yypv;
	register short *yyxi;

	yystate = 0;
	yychar = -1;
	yynerrs = 0;
	yyerrflag = 0;
	yyps= yys -1;
	yypv= yyv -1;

 yystack:    /* put a state and value onto the stack */

#ifdef YYDEBUG
	if( yydebug  ) printf( "state %d, char 0%o\n", yystate, yychar );
#endif
		if( ++yyps> &yys[YYMAXDEPTH] ) { yyerror( "yacc stack overflow" ); return(1); }
		*yyps = yystate;
		++yypv;
		*yypv = yyval;

 yynewstate:

	yyn = yypact[yystate];

	if( yyn<= YYFLAG ) goto yydefault; /* simple state */

	if( yychar<0 ) if( (yychar=yylex())<0 ) yychar=0;
	if( (yyn += yychar)<0 || yyn >= YYLAST ) goto yydefault;

	if( yychk[ yyn=yyact[ yyn ] ] == yychar ){ /* valid shift */
		yychar = -1;
		yyval = yylval;
		yystate = yyn;
		if( yyerrflag > 0 ) --yyerrflag;
		goto yystack;
		}

 yydefault:
	/* default state action */

	if( (yyn=yydef[yystate]) == -2 ) {
		if( yychar<0 ) if( (yychar=yylex())<0 ) yychar = 0;
		/* look through exception table */

		for( yyxi=yyexca; (*yyxi!= (-1)) || (yyxi[1]!=yystate) ; yyxi += 2 ) ; /* VOID */

		while( *(yyxi+=2) >= 0 ){
			if( *yyxi == yychar ) break;
			}
		if( (yyn = yyxi[1]) < 0 ) return(0);   /* accept */
		}

	if( yyn == 0 ){ /* error */
		/* error ... attempt to resume parsing */

		switch( yyerrflag ){

		case 0:   /* brand new error */

			yyerror( "syntax error" );
		yyerrlab:
			++yynerrs;

		case 1:
		case 2: /* incompletely recovered error ... try again */

			yyerrflag = 3;

			/* find a state where "error" is a legal shift action */

			while ( yyps >= yys ) {
			   yyn = yypact[*yyps] + YYERRCODE;
			   if( yyn>= 0 && yyn < YYLAST && yychk[yyact[yyn]] == YYERRCODE ){
			      yystate = yyact[yyn];  /* simulate a shift of "error" */
			      goto yystack;
			      }
			   yyn = yypact[*yyps];

			   /* the current yyps has no shift onn "error", pop stack */

#ifdef YYDEBUG
			   if( yydebug ) printf( "error recovery pops state %d, uncovers %d\n", *yyps, yyps[-1] );
#endif
			   --yyps;
			   --yypv;
			   }

			/* there is no state on the stack with an error shift ... abort */

	yyabort:
			return(1);


		case 3:  /* no shift yet; clobber input char */

#ifdef YYDEBUG
			if( yydebug ) printf( "error recovery discards char %d\n", yychar );
#endif

			if( yychar == 0 ) goto yyabort; /* don't discard EOF, quit */
			yychar = -1;
			goto yynewstate;   /* try again in the same state */

			}

		}

	/* reduction by production yyn */

#ifdef YYDEBUG
		if( yydebug ) printf("reduce %d\n",yyn);
#endif
		yyps -= yyr2[yyn];
		yypvt = yypv;
		yypv -= yyr2[yyn];
		yyval = yypv[1];
		yym=yyn;
			/* consult goto table to find next state */
		yyn = yyr1[yyn];
		yyj = yypgo[yyn] + *yyps + 1;
		if( yyj>=YYLAST || yychk[ yystate = yyact[yyj] ] != -yyn ) yystate = yyact[yypgo[yyn]];
		switch(yym){
			
case 1:
# line 18 "trn_expr.y"
{ trnexpr_low = yypvt[-0];
		  trnexpr_high = yypvt[-0];
		} break;
case 2:
# line 22 "trn_expr.y"
{ trnexpr_low = yypvt[-2];
		  trnexpr_high = yypvt[-0];
		} break;
case 3:
# line 26 "trn_expr.y"
{ trnexpr_low = dsc_public.highest_seen+1;
		  trnexpr_high = trnexpr_curmtg->last;
	        } break;
case 4:
# line 30 "trn_expr.y"
{ trnexpr_low = trnexpr_curmtg->first;
		  trnexpr_high = trnexpr_curmtg->last;
		} break;
case 5:
# line 34 "trn_expr.y"
{ trnexpr_low = trnexpr_curtrn->current;
		  trnexpr_high = trnexpr_curtrn->current;
		  trnexpr_aref = 1;
		} break;
case 19:
# line 58 "trn_expr.y"
{ yyval = yypvt[-2] - yypvt[-0]; } break;
case 20:
# line 60 "trn_expr.y"
{ yyval = yypvt[-2] + yypvt[-0]; } break;
		}
		goto yystack;  /* stack new state and value */

	}
