xref: /csrg-svn/usr.bin/f77/pass1.tahoe/lex.c (revision 37793)
137426Sbostic /*
237426Sbostic  * Copyright (c) 1980 Regents of the University of California.
337426Sbostic  * All rights reserved.  The Berkeley software License Agreement
437426Sbostic  * specifies the terms and conditions for redistribution.
537426Sbostic  */
637426Sbostic 
737426Sbostic #ifndef lint
837426Sbostic static char sccsid[] = "@(#)lex.c	5.1 (Berkeley) 6/7/85";
937426Sbostic #endif not lint
1037426Sbostic 
1137426Sbostic /*
1237426Sbostic  * lex.c
1337426Sbostic  *
1437426Sbostic  * Lexical scanner routines for the f77 compiler, pass 1, 4.2 BSD.
1537426Sbostic  *
1637426Sbostic  * University of Utah CS Dept modification history:
1737426Sbostic  *
1837426Sbostic  * $Log:	lex.c,v $
1937426Sbostic  * Revision 1.2  84/10/27  02:20:09  donn
2037426Sbostic  * Fixed bug where the input file and the name field of the include file
2137426Sbostic  * structure shared -- when the input file name was freed, the include file
2237426Sbostic  * name got stomped on, leading to peculiar error messages.
2337426Sbostic  *
2437426Sbostic  */
2537426Sbostic 
2637426Sbostic #include "defs.h"
2737426Sbostic #include "tokdefs.h"
28*37793Sbostic #include "pathnames.h"
2937426Sbostic 
3037426Sbostic # define BLANK	' '
3137426Sbostic # define MYQUOTE (2)
3237426Sbostic # define SEOF 0
3337426Sbostic 
3437426Sbostic /* card types */
3537426Sbostic 
3637426Sbostic # define STEOF 1
3737426Sbostic # define STINITIAL 2
3837426Sbostic # define STCONTINUE 3
3937426Sbostic 
4037426Sbostic /* lex states */
4137426Sbostic 
4237426Sbostic #define NEWSTMT	1
4337426Sbostic #define FIRSTTOKEN	2
4437426Sbostic #define OTHERTOKEN	3
4537426Sbostic #define RETEOS	4
4637426Sbostic 
4737426Sbostic 
4837426Sbostic LOCAL int stkey;
4937426Sbostic LOCAL int lastend = 1;
5037426Sbostic ftnint yystno;
5137426Sbostic flag intonly;
5237426Sbostic LOCAL long int stno;
5337426Sbostic LOCAL long int nxtstno;
5437426Sbostic LOCAL int parlev;
5537426Sbostic LOCAL int expcom;
5637426Sbostic LOCAL int expeql;
5737426Sbostic LOCAL char *nextch;
5837426Sbostic LOCAL char *lastch;
5937426Sbostic LOCAL char *nextcd 	= NULL;
6037426Sbostic LOCAL char *endcd;
6137426Sbostic LOCAL int prevlin;
6237426Sbostic LOCAL int thislin;
6337426Sbostic LOCAL int code;
6437426Sbostic LOCAL int lexstate	= NEWSTMT;
6537426Sbostic LOCAL char s[1390];
6637426Sbostic LOCAL char *send	= s+20*66;
6737426Sbostic LOCAL int nincl	= 0;
6837426Sbostic LOCAL char *newname = NULL;
6937426Sbostic 
7037426Sbostic struct Inclfile
7137426Sbostic 	{
7237426Sbostic 	struct Inclfile *inclnext;
7337426Sbostic 	FILEP inclfp;
7437426Sbostic 	char *inclname;
7537426Sbostic 	int incllno;
7637426Sbostic 	char *incllinp;
7737426Sbostic 	int incllen;
7837426Sbostic 	int inclcode;
7937426Sbostic 	ftnint inclstno;
8037426Sbostic 	} ;
8137426Sbostic 
8237426Sbostic LOCAL struct Inclfile *inclp	=  NULL;
8337426Sbostic LOCAL struct Keylist { char *keyname; int keyval; char notinf66; } ;
8437426Sbostic LOCAL struct Punctlist { char punchar; int punval; };
8537426Sbostic LOCAL struct Fmtlist { char fmtchar; int fmtval; };
8637426Sbostic LOCAL struct Dotlist { char *dotname; int dotval; };
8737426Sbostic LOCAL struct Keylist *keystart[26], *keyend[26];
8837426Sbostic 
8937426Sbostic 
9037426Sbostic 
9137426Sbostic 
9237426Sbostic inilex(name)
9337426Sbostic char *name;
9437426Sbostic {
9537426Sbostic nincl = 0;
9637426Sbostic inclp = NULL;
9737426Sbostic doinclude(name);
9837426Sbostic lexstate = NEWSTMT;
9937426Sbostic return(NO);
10037426Sbostic }
10137426Sbostic 
10237426Sbostic 
10337426Sbostic 
10437426Sbostic /* throw away the rest of the current line */
10537426Sbostic flline()
10637426Sbostic {
10737426Sbostic lexstate = RETEOS;
10837426Sbostic }
10937426Sbostic 
11037426Sbostic 
11137426Sbostic 
11237426Sbostic char *lexline(n)
11337426Sbostic int *n;
11437426Sbostic {
11537426Sbostic *n = (lastch - nextch) + 1;
11637426Sbostic return(nextch);
11737426Sbostic }
11837426Sbostic 
11937426Sbostic 
12037426Sbostic 
12137426Sbostic 
12237426Sbostic 
12337426Sbostic doinclude(name)
12437426Sbostic char *name;
12537426Sbostic {
12637426Sbostic FILEP fp;
12737426Sbostic struct Inclfile *t;
12837426Sbostic char temp[100];
12937426Sbostic register char *lastslash, *s;
13037426Sbostic 
13137426Sbostic if(inclp)
13237426Sbostic 	{
13337426Sbostic 	inclp->incllno = thislin;
13437426Sbostic 	inclp->inclcode = code;
13537426Sbostic 	inclp->inclstno = nxtstno;
13637426Sbostic 	if(nextcd)
13737426Sbostic 		inclp->incllinp = copyn(inclp->incllen = endcd-nextcd , nextcd);
13837426Sbostic 	else
13937426Sbostic 		inclp->incllinp = 0;
14037426Sbostic 	}
14137426Sbostic nextcd = NULL;
14237426Sbostic 
14337426Sbostic if(++nincl >= MAXINCLUDES)
14437426Sbostic 	fatal("includes nested too deep");
14537426Sbostic if(name[0] == '\0')
14637426Sbostic 	fp = stdin;
14737426Sbostic else if(name[0]=='/' || inclp==NULL)
14837426Sbostic 	fp = fopen(name, "r");
14937426Sbostic else	{
15037426Sbostic 	lastslash = NULL;
15137426Sbostic 	for(s = inclp->inclname ; *s ; ++s)
15237426Sbostic 		if(*s == '/')
15337426Sbostic 			lastslash = s;
15437426Sbostic 	if(lastslash)
15537426Sbostic 		{
15637426Sbostic 		*lastslash = '\0';
15737426Sbostic 		sprintf(temp, "%s/%s", inclp->inclname, name);
15837426Sbostic 		*lastslash = '/';
15937426Sbostic 		}
16037426Sbostic 	else
16137426Sbostic 		strcpy(temp, name);
16237426Sbostic 
16337426Sbostic 	if( (fp = fopen(temp, "r")) == NULL )
16437426Sbostic 		{
165*37793Sbostic 		sprintf(temp, "%s/%s", _PATH_INCLUDES, name);
16637426Sbostic 		fp = fopen(temp, "r");
16737426Sbostic 		}
16837426Sbostic 	if(fp)
16937426Sbostic 		name = copys(temp);
17037426Sbostic 	}
17137426Sbostic 
17237426Sbostic if( fp )
17337426Sbostic 	{
17437426Sbostic 	t = inclp;
17537426Sbostic 	inclp = ALLOC(Inclfile);
17637426Sbostic 	inclp->inclnext = t;
17737426Sbostic 	prevlin = thislin = 0;
17837426Sbostic 	inclp->inclname = name;
17937426Sbostic 	infname = copys(name);
18037426Sbostic 	infile = inclp->inclfp = fp;
18137426Sbostic 	}
18237426Sbostic else
18337426Sbostic 	{
18437426Sbostic 	fprintf(diagfile, "Cannot open file %s", name);
18537426Sbostic 	done(1);
18637426Sbostic 	}
18737426Sbostic }
18837426Sbostic 
18937426Sbostic 
19037426Sbostic 
19137426Sbostic 
19237426Sbostic LOCAL popinclude()
19337426Sbostic {
19437426Sbostic struct Inclfile *t;
19537426Sbostic register char *p;
19637426Sbostic register int k;
19737426Sbostic 
19837426Sbostic if(infile != stdin)
19937426Sbostic 	clf(&infile);
20037426Sbostic free(infname);
20137426Sbostic 
20237426Sbostic --nincl;
20337426Sbostic t = inclp->inclnext;
20437426Sbostic free(inclp->inclname);
20537426Sbostic free( (charptr) inclp);
20637426Sbostic inclp = t;
20737426Sbostic if(inclp == NULL)
20837426Sbostic 	return(NO);
20937426Sbostic 
21037426Sbostic infile = inclp->inclfp;
21137426Sbostic infname = copys(inclp->inclname);
21237426Sbostic prevlin = thislin = inclp->incllno;
21337426Sbostic code = inclp->inclcode;
21437426Sbostic stno = nxtstno = inclp->inclstno;
21537426Sbostic if(inclp->incllinp)
21637426Sbostic 	{
21737426Sbostic 	endcd = nextcd = s;
21837426Sbostic 	k = inclp->incllen;
21937426Sbostic 	p = inclp->incllinp;
22037426Sbostic 	while(--k >= 0)
22137426Sbostic 		*endcd++ = *p++;
22237426Sbostic 	free( (charptr) (inclp->incllinp) );
22337426Sbostic 	}
22437426Sbostic else
22537426Sbostic 	nextcd = NULL;
22637426Sbostic return(YES);
22737426Sbostic }
22837426Sbostic 
22937426Sbostic 
23037426Sbostic 
23137426Sbostic 
23237426Sbostic yylex()
23337426Sbostic {
23437426Sbostic static int  tokno;
23537426Sbostic 
23637426Sbostic 	switch(lexstate)
23737426Sbostic 	{
23837426Sbostic case NEWSTMT :	/* need a new statement */
23937426Sbostic 	if(getcds() == STEOF)
24037426Sbostic 		return(SEOF);
24137426Sbostic 	lastend =  stkey == SEND;
24237426Sbostic 	crunch();
24337426Sbostic 	tokno = 0;
24437426Sbostic 	lexstate = FIRSTTOKEN;
24537426Sbostic 	yystno = stno;
24637426Sbostic 	stno = nxtstno;
24737426Sbostic 	toklen = 0;
24837426Sbostic 	return(SLABEL);
24937426Sbostic 
25037426Sbostic first:
25137426Sbostic case FIRSTTOKEN :	/* first step on a statement */
25237426Sbostic 	analyz();
25337426Sbostic 	lexstate = OTHERTOKEN;
25437426Sbostic 	tokno = 1;
25537426Sbostic 	return(stkey);
25637426Sbostic 
25737426Sbostic case OTHERTOKEN :	/* return next token */
25837426Sbostic 	if(nextch > lastch)
25937426Sbostic 		goto reteos;
26037426Sbostic 	++tokno;
26137426Sbostic 	if( (stkey==SLOGIF || stkey==SELSEIF) && parlev==0 && tokno>3)
26237426Sbostic 		goto first;
26337426Sbostic 
26437426Sbostic 	if(stkey==SASSIGN && tokno==3 && nextch<lastch &&
26537426Sbostic 		nextch[0]=='t' && nextch[1]=='o')
26637426Sbostic 			{
26737426Sbostic 			nextch+=2;
26837426Sbostic 			return(STO);
26937426Sbostic 			}
27037426Sbostic 	return(gettok());
27137426Sbostic 
27237426Sbostic reteos:
27337426Sbostic case RETEOS:
27437426Sbostic 	lexstate = NEWSTMT;
27537426Sbostic 	return(SEOS);
27637426Sbostic 	}
27737426Sbostic fatali("impossible lexstate %d", lexstate);
27837426Sbostic /* NOTREACHED */
27937426Sbostic }
28037426Sbostic 
28137426Sbostic LOCAL getcds()
28237426Sbostic {
28337426Sbostic register char *p, *q;
28437426Sbostic 
28537426Sbostic 	if (newname)
28637426Sbostic 		{
28737426Sbostic 		free(infname);
28837426Sbostic 		infname = newname;
28937426Sbostic 		newname = NULL;
29037426Sbostic 		}
29137426Sbostic 
29237426Sbostic top:
29337426Sbostic 	if(nextcd == NULL)
29437426Sbostic 		{
29537426Sbostic 		code = getcd( nextcd = s );
29637426Sbostic 		stno = nxtstno;
29737426Sbostic 		if (newname)
29837426Sbostic 			{
29937426Sbostic 			free(infname);
30037426Sbostic 			infname = newname;
30137426Sbostic 			newname = NULL;
30237426Sbostic 			}
30337426Sbostic 		prevlin = thislin;
30437426Sbostic 		}
30537426Sbostic 	if(code == STEOF)
30637426Sbostic 		if( popinclude() )
30737426Sbostic 			goto top;
30837426Sbostic 		else
30937426Sbostic 			return(STEOF);
31037426Sbostic 
31137426Sbostic 	if(code == STCONTINUE)
31237426Sbostic 		{
31337426Sbostic 		if (newname)
31437426Sbostic 			{
31537426Sbostic 			free(infname);
31637426Sbostic 			infname = newname;
31737426Sbostic 			newname = NULL;
31837426Sbostic 			}
31937426Sbostic 		lineno = thislin;
32037426Sbostic 		err("illegal continuation card ignored");
32137426Sbostic 		nextcd = NULL;
32237426Sbostic 		goto top;
32337426Sbostic 		}
32437426Sbostic 
32537426Sbostic 	if(nextcd > s)
32637426Sbostic 		{
32737426Sbostic 		q = nextcd;
32837426Sbostic 		p = s;
32937426Sbostic 		while(q < endcd)
33037426Sbostic 			*p++ = *q++;
33137426Sbostic 		endcd = p;
33237426Sbostic 		}
33337426Sbostic 	for(nextcd = endcd ;
33437426Sbostic 		nextcd+66<=send && (code = getcd(nextcd))==STCONTINUE ;
33537426Sbostic 		nextcd = endcd )
33637426Sbostic 			;
33737426Sbostic 	nextch = s;
33837426Sbostic 	lastch = nextcd - 1;
33937426Sbostic 	if(nextcd >= send)
34037426Sbostic 		nextcd = NULL;
34137426Sbostic 	lineno = prevlin;
34237426Sbostic 	prevlin = thislin;
34337426Sbostic 	return(STINITIAL);
34437426Sbostic }
34537426Sbostic 
34637426Sbostic LOCAL getcd(b)
34737426Sbostic register char *b;
34837426Sbostic {
34937426Sbostic register int c;
35037426Sbostic register char *p, *bend;
35137426Sbostic int speclin;
35237426Sbostic static char a[6];
35337426Sbostic static char *aend	= a+6;
35437426Sbostic int num;
35537426Sbostic 
35637426Sbostic top:
35737426Sbostic 	endcd = b;
35837426Sbostic 	bend = b+66;
35937426Sbostic 	speclin = NO;
36037426Sbostic 
36137426Sbostic 	if( (c = getc(infile)) == '&')
36237426Sbostic 		{
36337426Sbostic 		a[0] = BLANK;
36437426Sbostic 		a[5] = 'x';
36537426Sbostic 		speclin = YES;
36637426Sbostic 		bend = send;
36737426Sbostic 		}
36837426Sbostic 	else if(c=='c' || c=='C' || c=='*')
36937426Sbostic 		{
37037426Sbostic 		while( (c = getc(infile)) != '\n')
37137426Sbostic 			if(c == EOF)
37237426Sbostic 				return(STEOF);
37337426Sbostic 		++thislin;
37437426Sbostic 		goto top;
37537426Sbostic 		}
37637426Sbostic 	else if(c == '#')
37737426Sbostic 		{
37837426Sbostic 		c = getc(infile);
37937426Sbostic 		while (c == BLANK || c == '\t')
38037426Sbostic 			c = getc(infile);
38137426Sbostic 
38237426Sbostic 		num = 0;
38337426Sbostic 		while (isdigit(c))
38437426Sbostic 			{
38537426Sbostic 			num = 10*num + c - '0';
38637426Sbostic 			c = getc(infile);
38737426Sbostic 			}
38837426Sbostic 		thislin = num - 1;
38937426Sbostic 
39037426Sbostic 		while (c == BLANK || c == '\t')
39137426Sbostic 			c = getc(infile);
39237426Sbostic 
39337426Sbostic 		if (c == '"')
39437426Sbostic 			{
39537426Sbostic 			char fname[1024];
39637426Sbostic 			int len = 0;
39737426Sbostic 
39837426Sbostic 			c = getc(infile);
39937426Sbostic 			while (c != '"' && c != '\n')
40037426Sbostic 				{
40137426Sbostic 				fname[len++] = c;
40237426Sbostic 				c = getc(infile);
40337426Sbostic 				}
40437426Sbostic 			fname[len++] = '\0';
40537426Sbostic 
40637426Sbostic 			if (newname)
40737426Sbostic 				free(newname);
40837426Sbostic 			newname = (char *) ckalloc(len);
40937426Sbostic 			strcpy(newname, fname);
41037426Sbostic 			}
41137426Sbostic 
41237426Sbostic 		while (c != '\n')
41337426Sbostic 			if (c == EOF)
41437426Sbostic 				return (STEOF);
41537426Sbostic 			else
41637426Sbostic 				c = getc(infile);
41737426Sbostic 		goto top;
41837426Sbostic 		}
41937426Sbostic 
42037426Sbostic 	else if(c != EOF)
42137426Sbostic 		{
42237426Sbostic 		/* a tab in columns 1-6 skips to column 7 */
42337426Sbostic 		ungetc(c, infile);
42437426Sbostic 		for(p=a; p<aend && (c=getc(infile)) != '\n' && c!=EOF; )
42537426Sbostic 			if(c == '\t')
42637426Sbostic 				{
42737426Sbostic 				while(p < aend)
42837426Sbostic 					*p++ = BLANK;
42937426Sbostic 				speclin = YES;
43037426Sbostic 				bend = send;
43137426Sbostic 				}
43237426Sbostic 			else
43337426Sbostic 				*p++ = c;
43437426Sbostic 		}
43537426Sbostic 	if(c == EOF)
43637426Sbostic 		return(STEOF);
43737426Sbostic 	if(c == '\n')
43837426Sbostic 		{
43937426Sbostic 		while(p < aend)
44037426Sbostic 			*p++ = BLANK;
44137426Sbostic 		if( ! speclin )
44237426Sbostic 			while(endcd < bend)
44337426Sbostic 				*endcd++ = BLANK;
44437426Sbostic 		}
44537426Sbostic 	else	{	/* read body of line */
44637426Sbostic 		while( endcd<bend && (c=getc(infile)) != '\n' && c!=EOF )
44737426Sbostic 			*endcd++ = c;
44837426Sbostic 		if(c == EOF)
44937426Sbostic 			return(STEOF);
45037426Sbostic 		if(c != '\n')
45137426Sbostic 			{
45237426Sbostic 			while( (c=getc(infile)) != '\n')
45337426Sbostic 				if(c == EOF)
45437426Sbostic 					return(STEOF);
45537426Sbostic 			}
45637426Sbostic 
45737426Sbostic 		if( ! speclin )
45837426Sbostic 			while(endcd < bend)
45937426Sbostic 				*endcd++ = BLANK;
46037426Sbostic 		}
46137426Sbostic 	++thislin;
46237426Sbostic 	if( !isspace(a[5]) && a[5]!='0')
46337426Sbostic 		return(STCONTINUE);
46437426Sbostic 	for(p=a; p<aend; ++p)
46537426Sbostic 		if( !isspace(*p) ) goto initline;
46637426Sbostic 	for(p = b ; p<endcd ; ++p)
46737426Sbostic 		if( !isspace(*p) ) goto initline;
46837426Sbostic 	goto top;
46937426Sbostic 
47037426Sbostic initline:
47137426Sbostic 	nxtstno = 0;
47237426Sbostic 	for(p = a ; p<a+5 ; ++p)
47337426Sbostic 		if( !isspace(*p) )
47437426Sbostic 			if(isdigit(*p))
47537426Sbostic 				nxtstno = 10*nxtstno + (*p - '0');
47637426Sbostic 			else	{
47737426Sbostic 				if (newname)
47837426Sbostic 					{
47937426Sbostic 					free(infname);
48037426Sbostic 					infname = newname;
48137426Sbostic 					newname = NULL;
48237426Sbostic 					}
48337426Sbostic 				lineno = thislin;
48437426Sbostic 				err("nondigit in statement number field");
48537426Sbostic 				nxtstno = 0;
48637426Sbostic 				break;
48737426Sbostic 				}
48837426Sbostic 	return(STINITIAL);
48937426Sbostic }
49037426Sbostic 
49137426Sbostic LOCAL crunch()
49237426Sbostic {
49337426Sbostic register char *i, *j, *j0, *j1, *prvstr;
49437426Sbostic int ten, nh, quote;
49537426Sbostic 
49637426Sbostic /* i is the next input character to be looked at
49737426Sbostic j is the next output character */
49837426Sbostic parlev = 0;
49937426Sbostic expcom = 0;	/* exposed ','s */
50037426Sbostic expeql = 0;	/* exposed equal signs */
50137426Sbostic j = s;
50237426Sbostic prvstr = s;
50337426Sbostic for(i=s ; i<=lastch ; ++i)
50437426Sbostic 	{
50537426Sbostic 	if(isspace(*i) )
50637426Sbostic 		continue;
50737426Sbostic 	if(*i=='\'' ||  *i=='"')
50837426Sbostic 		{
50937426Sbostic 		quote = *i;
51037426Sbostic 		*j = MYQUOTE; /* special marker */
51137426Sbostic 		for(;;)
51237426Sbostic 			{
51337426Sbostic 			if(++i > lastch)
51437426Sbostic 				{
51537426Sbostic 				err("unbalanced quotes; closing quote supplied");
51637426Sbostic 				break;
51737426Sbostic 				}
51837426Sbostic 			if(*i == quote)
51937426Sbostic 				if(i<lastch && i[1]==quote) ++i;
52037426Sbostic 				else break;
52137426Sbostic 			else if(*i=='\\' && i<lastch)
52237426Sbostic 				switch(*++i)
52337426Sbostic 					{
52437426Sbostic 					case 't':
52537426Sbostic 						*i = '\t'; break;
52637426Sbostic 					case 'b':
52737426Sbostic 						*i = '\b'; break;
52837426Sbostic 					case 'n':
52937426Sbostic 						*i = '\n'; break;
53037426Sbostic 					case 'f':
53137426Sbostic 						*i = '\f'; break;
53237426Sbostic 					case 'v':
53337426Sbostic 						*i = '\v'; break;
53437426Sbostic 					case '0':
53537426Sbostic 						*i = '\0'; break;
53637426Sbostic 					default:
53737426Sbostic 						break;
53837426Sbostic 					}
53937426Sbostic 			*++j = *i;
54037426Sbostic 			}
54137426Sbostic 		j[1] = MYQUOTE;
54237426Sbostic 		j += 2;
54337426Sbostic 		prvstr = j;
54437426Sbostic 		}
54537426Sbostic 	else if( (*i=='h' || *i=='H')  && j>prvstr)	/* test for Hollerith strings */
54637426Sbostic 		{
54737426Sbostic 		if( ! isdigit(j[-1])) goto copychar;
54837426Sbostic 		nh = j[-1] - '0';
54937426Sbostic 		ten = 10;
55037426Sbostic 		j1 = prvstr - 1;
55137426Sbostic 		if (j1<j-5) j1=j-5;
55237426Sbostic 		for(j0=j-2 ; j0>j1; -- j0)
55337426Sbostic 			{
55437426Sbostic 			if( ! isdigit(*j0 ) ) break;
55537426Sbostic 			nh += ten * (*j0-'0');
55637426Sbostic 			ten*=10;
55737426Sbostic 			}
55837426Sbostic 		if(j0 <= j1) goto copychar;
55937426Sbostic /* a hollerith must be preceded by a punctuation mark.
56037426Sbostic    '*' is possible only as repetition factor in a data statement
56137426Sbostic    not, in particular, in character*2h
56237426Sbostic */
56337426Sbostic 
56437426Sbostic 		if( !(*j0=='*'&&s[0]=='d') && *j0!='/' && *j0!='(' &&
56537426Sbostic 			*j0!=',' && *j0!='=' && *j0!='.')
56637426Sbostic 				goto copychar;
56737426Sbostic 		if(i+nh > lastch)
56837426Sbostic 			{
56937426Sbostic 			erri("%dH too big", nh);
57037426Sbostic 			nh = lastch - i;
57137426Sbostic 			}
57237426Sbostic 		j0[1] = MYQUOTE; /* special marker */
57337426Sbostic 		j = j0 + 1;
57437426Sbostic 		while(nh-- > 0)
57537426Sbostic 			{
57637426Sbostic 			if(*++i == '\\')
57737426Sbostic 				switch(*++i)
57837426Sbostic 					{
57937426Sbostic 					case 't':
58037426Sbostic 						*i = '\t'; break;
58137426Sbostic 					case 'b':
58237426Sbostic 						*i = '\b'; break;
58337426Sbostic 					case 'n':
58437426Sbostic 						*i = '\n'; break;
58537426Sbostic 					case 'f':
58637426Sbostic 						*i = '\f'; break;
58737426Sbostic 					case '0':
58837426Sbostic 						*i = '\0'; break;
58937426Sbostic 					default:
59037426Sbostic 						break;
59137426Sbostic 					}
59237426Sbostic 			*++j = *i;
59337426Sbostic 			}
59437426Sbostic 		j[1] = MYQUOTE;
59537426Sbostic 		j+=2;
59637426Sbostic 		prvstr = j;
59737426Sbostic 		}
59837426Sbostic 	else	{
59937426Sbostic 		if(*i == '(') ++parlev;
60037426Sbostic 		else if(*i == ')') --parlev;
60137426Sbostic 		else if(parlev == 0)
60237426Sbostic 			if(*i == '=') expeql = 1;
60337426Sbostic 			else if(*i == ',') expcom = 1;
60437426Sbostic copychar:		/*not a string or space -- copy, shifting case if necessary */
60537426Sbostic 		if(shiftcase && isupper(*i))
60637426Sbostic 			*j++ = tolower(*i);
60737426Sbostic 		else	*j++ = *i;
60837426Sbostic 		}
60937426Sbostic 	}
61037426Sbostic lastch = j - 1;
61137426Sbostic nextch = s;
61237426Sbostic }
61337426Sbostic 
61437426Sbostic LOCAL analyz()
61537426Sbostic {
61637426Sbostic register char *i;
61737426Sbostic 
61837426Sbostic 	if(parlev != 0)
61937426Sbostic 		{
62037426Sbostic 		err("unbalanced parentheses, statement skipped");
62137426Sbostic 		stkey = SUNKNOWN;
62237426Sbostic 		return;
62337426Sbostic 		}
62437426Sbostic 	if(nextch+2<=lastch && nextch[0]=='i' && nextch[1]=='f' && nextch[2]=='(')
62537426Sbostic 		{
62637426Sbostic /* assignment or if statement -- look at character after balancing paren */
62737426Sbostic 		parlev = 1;
62837426Sbostic 		for(i=nextch+3 ; i<=lastch; ++i)
62937426Sbostic 			if(*i == (MYQUOTE))
63037426Sbostic 				{
63137426Sbostic 				while(*++i != MYQUOTE)
63237426Sbostic 					;
63337426Sbostic 				}
63437426Sbostic 			else if(*i == '(')
63537426Sbostic 				++parlev;
63637426Sbostic 			else if(*i == ')')
63737426Sbostic 				{
63837426Sbostic 				if(--parlev == 0)
63937426Sbostic 					break;
64037426Sbostic 				}
64137426Sbostic 		if(i >= lastch)
64237426Sbostic 			stkey = SLOGIF;
64337426Sbostic 		else if(i[1] == '=')
64437426Sbostic 			stkey = SLET;
64537426Sbostic 		else if( isdigit(i[1]) )
64637426Sbostic 			stkey = SARITHIF;
64737426Sbostic 		else	stkey = SLOGIF;
64837426Sbostic 		if(stkey != SLET)
64937426Sbostic 			nextch += 2;
65037426Sbostic 		}
65137426Sbostic 	else if(expeql) /* may be an assignment */
65237426Sbostic 		{
65337426Sbostic 		if(expcom && nextch<lastch &&
65437426Sbostic 			nextch[0]=='d' && nextch[1]=='o')
65537426Sbostic 				{
65637426Sbostic 				stkey = SDO;
65737426Sbostic 				nextch += 2;
65837426Sbostic 				}
65937426Sbostic 		else	stkey = SLET;
66037426Sbostic 		}
66137426Sbostic /* otherwise search for keyword */
66237426Sbostic 	else	{
66337426Sbostic 		stkey = getkwd();
66437426Sbostic 		if(stkey==SGOTO && lastch>=nextch)
66537426Sbostic 			if(nextch[0]=='(')
66637426Sbostic 				stkey = SCOMPGOTO;
66737426Sbostic 			else if(isalpha(nextch[0]))
66837426Sbostic 				stkey = SASGOTO;
66937426Sbostic 		}
67037426Sbostic 	parlev = 0;
67137426Sbostic }
67237426Sbostic 
67337426Sbostic 
67437426Sbostic 
67537426Sbostic LOCAL getkwd()
67637426Sbostic {
67737426Sbostic register char *i, *j;
67837426Sbostic register struct Keylist *pk, *pend;
67937426Sbostic int k;
68037426Sbostic 
68137426Sbostic if(! isalpha(nextch[0]) )
68237426Sbostic 	return(SUNKNOWN);
68337426Sbostic k = nextch[0] - 'a';
68437426Sbostic if(pk = keystart[k])
68537426Sbostic 	for(pend = keyend[k] ; pk<=pend ; ++pk )
68637426Sbostic 		{
68737426Sbostic 		i = pk->keyname;
68837426Sbostic 		j = nextch;
68937426Sbostic 		while(*++i==*++j && *i!='\0')
69037426Sbostic 			;
69137426Sbostic 		if(*i=='\0' && j<=lastch+1)
69237426Sbostic 			{
69337426Sbostic 			nextch = j;
69437426Sbostic 			if(no66flag && pk->notinf66)
69537426Sbostic 				errstr("Not a Fortran 66 keyword: %s",
69637426Sbostic 					pk->keyname);
69737426Sbostic 			return(pk->keyval);
69837426Sbostic 			}
69937426Sbostic 		}
70037426Sbostic return(SUNKNOWN);
70137426Sbostic }
70237426Sbostic 
70337426Sbostic 
70437426Sbostic 
70537426Sbostic initkey()
70637426Sbostic {
70737426Sbostic extern struct Keylist keys[];
70837426Sbostic register struct Keylist *p;
70937426Sbostic register int i,j;
71037426Sbostic 
71137426Sbostic for(i = 0 ; i<26 ; ++i)
71237426Sbostic 	keystart[i] = NULL;
71337426Sbostic 
71437426Sbostic for(p = keys ; p->keyname ; ++p)
71537426Sbostic 	{
71637426Sbostic 	j = p->keyname[0] - 'a';
71737426Sbostic 	if(keystart[j] == NULL)
71837426Sbostic 		keystart[j] = p;
71937426Sbostic 	keyend[j] = p;
72037426Sbostic 	}
72137426Sbostic }
72237426Sbostic 
72337426Sbostic LOCAL gettok()
72437426Sbostic {
72537426Sbostic int havdot, havexp, havdbl;
72637426Sbostic int radix, val;
72737426Sbostic extern struct Punctlist puncts[];
72837426Sbostic struct Punctlist *pp;
72937426Sbostic extern struct Fmtlist fmts[];
73037426Sbostic extern struct Dotlist dots[];
73137426Sbostic struct Dotlist *pd;
73237426Sbostic 
73337426Sbostic char *i, *j, *n1, *p;
73437426Sbostic 
73537426Sbostic 	if(*nextch == (MYQUOTE))
73637426Sbostic 		{
73737426Sbostic 		++nextch;
73837426Sbostic 		p = token;
73937426Sbostic 		while(*nextch != MYQUOTE)
74037426Sbostic 			*p++ = *nextch++;
74137426Sbostic 		++nextch;
74237426Sbostic 		toklen = p - token;
74337426Sbostic 		*p = '\0';
74437426Sbostic 		return (SHOLLERITH);
74537426Sbostic 		}
74637426Sbostic /*
74737426Sbostic 	if(stkey == SFORMAT)
74837426Sbostic 		{
74937426Sbostic 		for(pf = fmts; pf->fmtchar; ++pf)
75037426Sbostic 			{
75137426Sbostic 			if(*nextch == pf->fmtchar)
75237426Sbostic 				{
75337426Sbostic 				++nextch;
75437426Sbostic 				if(pf->fmtval == SLPAR)
75537426Sbostic 					++parlev;
75637426Sbostic 				else if(pf->fmtval == SRPAR)
75737426Sbostic 					--parlev;
75837426Sbostic 				return(pf->fmtval);
75937426Sbostic 				}
76037426Sbostic 			}
76137426Sbostic 		if( isdigit(*nextch) )
76237426Sbostic 			{
76337426Sbostic 			p = token;
76437426Sbostic 			*p++ = *nextch++;
76537426Sbostic 			while(nextch<=lastch && isdigit(*nextch) )
76637426Sbostic 				*p++ = *nextch++;
76737426Sbostic 			toklen = p - token;
76837426Sbostic 			*p = '\0';
76937426Sbostic 			if(nextch<=lastch && *nextch=='p')
77037426Sbostic 				{
77137426Sbostic 				++nextch;
77237426Sbostic 				return(SSCALE);
77337426Sbostic 				}
77437426Sbostic 			else	return(SICON);
77537426Sbostic 			}
77637426Sbostic 		if( isalpha(*nextch) )
77737426Sbostic 			{
77837426Sbostic 			p = token;
77937426Sbostic 			*p++ = *nextch++;
78037426Sbostic 			while(nextch<=lastch &&
78137426Sbostic 				(*nextch=='.' || isdigit(*nextch) || isalpha(*nextch) ))
78237426Sbostic 					*p++ = *nextch++;
78337426Sbostic 			toklen = p - token;
78437426Sbostic 			*p = '\0';
78537426Sbostic 			return(SFIELD);
78637426Sbostic 			}
78737426Sbostic 		goto badchar;
78837426Sbostic 		}
78937426Sbostic /* Not a format statement */
79037426Sbostic 
79137426Sbostic if(needkwd)
79237426Sbostic 	{
79337426Sbostic 	needkwd = 0;
79437426Sbostic 	return( getkwd() );
79537426Sbostic 	}
79637426Sbostic 
79737426Sbostic 	for(pp=puncts; pp->punchar; ++pp)
79837426Sbostic 		if(*nextch == pp->punchar)
79937426Sbostic 			{
80037426Sbostic 			if( (*nextch=='*' || *nextch=='/') &&
80137426Sbostic 				nextch<lastch && nextch[1]==nextch[0])
80237426Sbostic 					{
80337426Sbostic 					if(*nextch == '*')
80437426Sbostic 						val = SPOWER;
80537426Sbostic 					else	val = SCONCAT;
80637426Sbostic 					nextch+=2;
80737426Sbostic 					}
80837426Sbostic 			else	{
80937426Sbostic 				val = pp->punval;
81037426Sbostic 				if(val==SLPAR)
81137426Sbostic 					++parlev;
81237426Sbostic 				else if(val==SRPAR)
81337426Sbostic 					--parlev;
81437426Sbostic 				++nextch;
81537426Sbostic 				}
81637426Sbostic 			return(val);
81737426Sbostic 			}
81837426Sbostic 	if(*nextch == '.')
81937426Sbostic 		if(nextch >= lastch) goto badchar;
82037426Sbostic 		else if(isdigit(nextch[1])) goto numconst;
82137426Sbostic 		else	{
82237426Sbostic 			for(pd=dots ; (j=pd->dotname) ; ++pd)
82337426Sbostic 				{
82437426Sbostic 				for(i=nextch+1 ; i<=lastch ; ++i)
82537426Sbostic 					if(*i != *j) break;
82637426Sbostic 					else if(*i != '.') ++j;
82737426Sbostic 					else	{
82837426Sbostic 						nextch = i+1;
82937426Sbostic 						return(pd->dotval);
83037426Sbostic 						}
83137426Sbostic 				}
83237426Sbostic 			goto badchar;
83337426Sbostic 			}
83437426Sbostic 	if( isalpha(*nextch) )
83537426Sbostic 		{
83637426Sbostic 		p = token;
83737426Sbostic 		*p++ = *nextch++;
83837426Sbostic 		while(nextch<=lastch)
83937426Sbostic 			if( isalpha(*nextch) || isdigit(*nextch) )
84037426Sbostic 				*p++ = *nextch++;
84137426Sbostic 			else break;
84237426Sbostic 		toklen = p - token;
84337426Sbostic 		*p = '\0';
84437426Sbostic 		if(inioctl && nextch<=lastch && *nextch=='=')
84537426Sbostic 			{
84637426Sbostic 			++nextch;
84737426Sbostic 			return(SNAMEEQ);
84837426Sbostic 			}
84937426Sbostic 		if(toklen>8 && eqn(8,token,"function") && isalpha(token[8]) &&
85037426Sbostic 			nextch<lastch && nextch[0]=='(' &&
85137426Sbostic 			(nextch[1]==')' | isalpha(nextch[1])) )
85237426Sbostic 				{
85337426Sbostic 				nextch -= (toklen - 8);
85437426Sbostic 				return(SFUNCTION);
85537426Sbostic 				}
85637426Sbostic 		if(toklen > VL)
85737426Sbostic 			{
85837426Sbostic 			char buff[30];
85937426Sbostic 			sprintf(buff, "name %s too long, truncated to %d",
86037426Sbostic 				token, VL);
86137426Sbostic 			err(buff);
86237426Sbostic 			toklen = VL;
86337426Sbostic 			token[VL] = '\0';
86437426Sbostic 			}
86537426Sbostic 		if(toklen==1 && *nextch==MYQUOTE)
86637426Sbostic 			{
86737426Sbostic 			switch(token[0])
86837426Sbostic 				{
86937426Sbostic 				case 'z':  case 'Z':
87037426Sbostic 				case 'x':  case 'X':
87137426Sbostic 					radix = 16; break;
87237426Sbostic 				case 'o':  case 'O':
87337426Sbostic 					radix = 8; break;
87437426Sbostic 				case 'b':  case 'B':
87537426Sbostic 					radix = 2; break;
87637426Sbostic 				default:
87737426Sbostic 					err("bad bit identifier");
87837426Sbostic 					return(SNAME);
87937426Sbostic 				}
88037426Sbostic 			++nextch;
88137426Sbostic 			for(p = token ; *nextch!=MYQUOTE ; )
88237426Sbostic 				if ( *nextch == BLANK || *nextch == '\t')
88337426Sbostic 					nextch++;
88437426Sbostic 				else
88537426Sbostic 					{
88637426Sbostic 					if (isupper(*nextch))
88737426Sbostic 						*nextch = tolower(*nextch);
88837426Sbostic 					if (hextoi(*p++ = *nextch++) >= radix)
88937426Sbostic 						{
89037426Sbostic 						err("invalid binary character");
89137426Sbostic 						break;
89237426Sbostic 						}
89337426Sbostic 					}
89437426Sbostic 			++nextch;
89537426Sbostic 			toklen = p - token;
89637426Sbostic 			return( radix==16 ? SHEXCON :
89737426Sbostic 				(radix==8 ? SOCTCON : SBITCON) );
89837426Sbostic 			}
89937426Sbostic 		return(SNAME);
90037426Sbostic 		}
90137426Sbostic 	if( ! isdigit(*nextch) ) goto badchar;
90237426Sbostic numconst:
90337426Sbostic 	havdot = NO;
90437426Sbostic 	havexp = NO;
90537426Sbostic 	havdbl = NO;
90637426Sbostic 	for(n1 = nextch ; nextch<=lastch ; ++nextch)
90737426Sbostic 		{
90837426Sbostic 		if(*nextch == '.')
90937426Sbostic 			if(havdot) break;
91037426Sbostic 			else if(nextch+2<=lastch && isalpha(nextch[1])
91137426Sbostic 				&& isalpha(nextch[2]))
91237426Sbostic 					break;
91337426Sbostic 			else	havdot = YES;
91437426Sbostic 		else if( !intonly && (*nextch=='d' || *nextch=='e') )
91537426Sbostic 			{
91637426Sbostic 			p = nextch;
91737426Sbostic 			havexp = YES;
91837426Sbostic 			if(*nextch == 'd')
91937426Sbostic 				havdbl = YES;
92037426Sbostic 			if(nextch<lastch)
92137426Sbostic 				if(nextch[1]=='+' || nextch[1]=='-')
92237426Sbostic 					++nextch;
92337426Sbostic 			if( (nextch >= lastch) || ! isdigit(*++nextch) )
92437426Sbostic 				{
92537426Sbostic 				nextch = p;
92637426Sbostic 				havdbl = havexp = NO;
92737426Sbostic 				break;
92837426Sbostic 				}
92937426Sbostic 			for(++nextch ;
93037426Sbostic 				nextch<=lastch && isdigit(*nextch);
93137426Sbostic 				++nextch);
93237426Sbostic 			break;
93337426Sbostic 			}
93437426Sbostic 		else if( ! isdigit(*nextch) )
93537426Sbostic 			break;
93637426Sbostic 		}
93737426Sbostic 	p = token;
93837426Sbostic 	i = n1;
93937426Sbostic 	while(i < nextch)
94037426Sbostic 		*p++ = *i++;
94137426Sbostic 	toklen = p - token;
94237426Sbostic 	*p = '\0';
94337426Sbostic 	if(havdbl) return(SDCON);
94437426Sbostic 	if(havdot || havexp) return(SRCON);
94537426Sbostic 	return(SICON);
94637426Sbostic badchar:
94737426Sbostic 	s[0] = *nextch++;
94837426Sbostic 	return(SUNKNOWN);
94937426Sbostic }
95037426Sbostic 
95137426Sbostic /* KEYWORD AND SPECIAL CHARACTER TABLES
95237426Sbostic */
95337426Sbostic 
95437426Sbostic struct Punctlist puncts[ ] =
95537426Sbostic 	{
95637426Sbostic 	'(', SLPAR,
95737426Sbostic 	')', SRPAR,
95837426Sbostic 	'=', SEQUALS,
95937426Sbostic 	',', SCOMMA,
96037426Sbostic 	'+', SPLUS,
96137426Sbostic 	'-', SMINUS,
96237426Sbostic 	'*', SSTAR,
96337426Sbostic 	'/', SSLASH,
96437426Sbostic 	'$', SCURRENCY,
96537426Sbostic 	':', SCOLON,
96637426Sbostic 	0, 0 } ;
96737426Sbostic 
96837426Sbostic /*
96937426Sbostic LOCAL struct Fmtlist  fmts[ ] =
97037426Sbostic 	{
97137426Sbostic 	'(', SLPAR,
97237426Sbostic 	')', SRPAR,
97337426Sbostic 	'/', SSLASH,
97437426Sbostic 	',', SCOMMA,
97537426Sbostic 	'-', SMINUS,
97637426Sbostic 	':', SCOLON,
97737426Sbostic 	0, 0 } ;
97837426Sbostic */
97937426Sbostic 
98037426Sbostic LOCAL struct Dotlist  dots[ ] =
98137426Sbostic 	{
98237426Sbostic 	"and.", SAND,
98337426Sbostic 	"or.", SOR,
98437426Sbostic 	"not.", SNOT,
98537426Sbostic 	"true.", STRUE,
98637426Sbostic 	"false.", SFALSE,
98737426Sbostic 	"eq.", SEQ,
98837426Sbostic 	"ne.", SNE,
98937426Sbostic 	"lt.", SLT,
99037426Sbostic 	"le.", SLE,
99137426Sbostic 	"gt.", SGT,
99237426Sbostic 	"ge.", SGE,
99337426Sbostic 	"neqv.", SNEQV,
99437426Sbostic 	"eqv.", SEQV,
99537426Sbostic 	0, 0 } ;
99637426Sbostic 
99737426Sbostic LOCAL struct Keylist  keys[ ] =
99837426Sbostic 	{
99937426Sbostic 	 	{ "assign",  SASSIGN  },
100037426Sbostic 	 	{ "automatic",  SAUTOMATIC, YES  },
100137426Sbostic 	 	{ "backspace",  SBACKSPACE  },
100237426Sbostic 	 	{ "blockdata",  SBLOCK  },
100337426Sbostic 	 	{ "call",  SCALL  },
100437426Sbostic 	 	{ "character",  SCHARACTER, YES  },
100537426Sbostic 	 	{ "close",  SCLOSE, YES  },
100637426Sbostic 	 	{ "common",  SCOMMON  },
100737426Sbostic 	 	{ "complex",  SCOMPLEX  },
100837426Sbostic 	 	{ "continue",  SCONTINUE  },
100937426Sbostic 	 	{ "data",  SDATA  },
101037426Sbostic 	 	{ "dimension",  SDIMENSION  },
101137426Sbostic 	 	{ "doubleprecision",  SDOUBLE  },
101237426Sbostic 	 	{ "doublecomplex", SDCOMPLEX, YES  },
101337426Sbostic 	 	{ "elseif",  SELSEIF, YES  },
101437426Sbostic 	 	{ "else",  SELSE, YES  },
101537426Sbostic 	 	{ "endfile",  SENDFILE  },
101637426Sbostic 	 	{ "endif",  SENDIF, YES  },
101737426Sbostic 	 	{ "end",  SEND  },
101837426Sbostic 	 	{ "entry",  SENTRY, YES  },
101937426Sbostic 	 	{ "equivalence",  SEQUIV  },
102037426Sbostic 	 	{ "external",  SEXTERNAL  },
102137426Sbostic 	 	{ "format",  SFORMAT  },
102237426Sbostic 	 	{ "function",  SFUNCTION  },
102337426Sbostic 	 	{ "goto",  SGOTO  },
102437426Sbostic 	 	{ "implicit",  SIMPLICIT, YES  },
102537426Sbostic 	 	{ "include",  SINCLUDE, YES  },
102637426Sbostic 	 	{ "inquire",  SINQUIRE, YES  },
102737426Sbostic 	 	{ "intrinsic",  SINTRINSIC, YES  },
102837426Sbostic 	 	{ "integer",  SINTEGER  },
102937426Sbostic 	 	{ "logical",  SLOGICAL  },
103037426Sbostic #ifdef NAMELIST
103137426Sbostic 		{ "namelist", SNAMELIST, YES },
103237426Sbostic #endif
103337426Sbostic 		{ "none", SUNDEFINED, YES },
103437426Sbostic 	 	{ "open",  SOPEN, YES  },
103537426Sbostic 	 	{ "parameter",  SPARAM, YES  },
103637426Sbostic 	 	{ "pause",  SPAUSE  },
103737426Sbostic 	 	{ "print",  SPRINT  },
103837426Sbostic 	 	{ "program",  SPROGRAM, YES  },
103937426Sbostic 	 	{ "punch",  SPUNCH, YES  },
104037426Sbostic 	 	{ "read",  SREAD  },
104137426Sbostic 	 	{ "real",  SREAL  },
104237426Sbostic 	 	{ "return",  SRETURN  },
104337426Sbostic 	 	{ "rewind",  SREWIND  },
104437426Sbostic 	 	{ "save",  SSAVE, YES  },
104537426Sbostic 	 	{ "static",  SSTATIC, YES  },
104637426Sbostic 	 	{ "stop",  SSTOP  },
104737426Sbostic 	 	{ "subroutine",  SSUBROUTINE  },
104837426Sbostic 	 	{ "then",  STHEN, YES  },
104937426Sbostic 	 	{ "undefined", SUNDEFINED, YES  },
105037426Sbostic 	 	{ "write",  SWRITE  },
105137426Sbostic 			{ 0, 0 }
105237426Sbostic 	};
1053