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