xref: /csrg-svn/usr.bin/f77/pass1.vax/lex.c (revision 47955)
1*47955Sbostic /*-
2*47955Sbostic  * Copyright (c) 1980 The Regents of the University of California.
3*47955Sbostic  * All rights reserved.
4*47955Sbostic  *
5*47955Sbostic  * %sccs.include.proprietary.c%
622840Smckusick  */
722840Smckusick 
822840Smckusick #ifndef lint
9*47955Sbostic static char sccsid[] = "@(#)lex.c	5.5 (Berkeley) 04/12/91";
10*47955Sbostic #endif /* not lint */
1122840Smckusick 
1222840Smckusick /*
1322840Smckusick  * lex.c
1422840Smckusick  *
1522840Smckusick  * Lexical scanner routines for the f77 compiler, pass 1, 4.2 BSD.
1622840Smckusick  *
1722840Smckusick  * University of Utah CS Dept modification history:
1822840Smckusick  *
1922840Smckusick  * $Log:	lex.c,v $
2025742Sdonn  * Revision 5.4  86/01/07  14:01:13  donn
2125742Sdonn  * Fix the scanning for character constants in gettok() so that it handles
2225742Sdonn  * the case when an error has occurred and there is no closing quote.
2325742Sdonn  *
2425742Sdonn  * Revision 5.3  85/11/25  00:24:06  donn
2525742Sdonn  * 4.3 beta
2625742Sdonn  *
2724481Sdonn  * Revision 5.2  85/08/10  04:45:41  donn
2824481Sdonn  * Jerry Berkman's changes to ifdef 66 code and handle -r8/double flag.
2924481Sdonn  *
3024481Sdonn  * Revision 5.1  85/08/10  03:48:20  donn
3124481Sdonn  * 4.3 alpha
3224481Sdonn  *
3322840Smckusick  * Revision 1.2  84/10/27  02:20:09  donn
3422840Smckusick  * Fixed bug where the input file and the name field of the include file
3522840Smckusick  * structure shared -- when the input file name was freed, the include file
3622840Smckusick  * name got stomped on, leading to peculiar error messages.
3722840Smckusick  *
3822840Smckusick  */
3922840Smckusick 
4022840Smckusick #include "defs.h"
4122840Smckusick #include "tokdefs.h"
4237795Sbostic #include "pathnames.h"
4322840Smckusick 
4422840Smckusick # define BLANK	' '
4522840Smckusick # define MYQUOTE (2)
4622840Smckusick # define SEOF 0
4722840Smckusick 
4822840Smckusick /* card types */
4922840Smckusick 
5022840Smckusick # define STEOF 1
5122840Smckusick # define STINITIAL 2
5222840Smckusick # define STCONTINUE 3
5322840Smckusick 
5422840Smckusick /* lex states */
5522840Smckusick 
5622840Smckusick #define NEWSTMT	1
5722840Smckusick #define FIRSTTOKEN	2
5822840Smckusick #define OTHERTOKEN	3
5922840Smckusick #define RETEOS	4
6022840Smckusick 
6122840Smckusick 
6222840Smckusick LOCAL int stkey;
6322840Smckusick LOCAL int lastend = 1;
6422840Smckusick ftnint yystno;
6522840Smckusick flag intonly;
6622840Smckusick LOCAL long int stno;
6722840Smckusick LOCAL long int nxtstno;
6822840Smckusick LOCAL int parlev;
6922840Smckusick LOCAL int expcom;
7022840Smckusick LOCAL int expeql;
7122840Smckusick LOCAL char *nextch;
7222840Smckusick LOCAL char *lastch;
7322840Smckusick LOCAL char *nextcd 	= NULL;
7422840Smckusick LOCAL char *endcd;
7522840Smckusick LOCAL int prevlin;
7622840Smckusick LOCAL int thislin;
7722840Smckusick LOCAL int code;
7822840Smckusick LOCAL int lexstate	= NEWSTMT;
7922840Smckusick LOCAL char s[1390];
8022840Smckusick LOCAL char *send	= s+20*66;
8122840Smckusick LOCAL int nincl	= 0;
8222840Smckusick LOCAL char *newname = NULL;
8322840Smckusick 
8422840Smckusick struct Inclfile
8522840Smckusick 	{
8622840Smckusick 	struct Inclfile *inclnext;
8722840Smckusick 	FILEP inclfp;
8822840Smckusick 	char *inclname;
8922840Smckusick 	int incllno;
9022840Smckusick 	char *incllinp;
9122840Smckusick 	int incllen;
9222840Smckusick 	int inclcode;
9322840Smckusick 	ftnint inclstno;
9422840Smckusick 	} ;
9522840Smckusick 
9622840Smckusick LOCAL struct Inclfile *inclp	=  NULL;
9722840Smckusick LOCAL struct Keylist { char *keyname; int keyval; char notinf66; } ;
9822840Smckusick LOCAL struct Punctlist { char punchar; int punval; };
9922840Smckusick LOCAL struct Fmtlist { char fmtchar; int fmtval; };
10022840Smckusick LOCAL struct Dotlist { char *dotname; int dotval; };
10122840Smckusick LOCAL struct Keylist *keystart[26], *keyend[26];
10222840Smckusick 
10322840Smckusick 
10422840Smckusick 
10522840Smckusick 
inilex(name)10622840Smckusick inilex(name)
10722840Smckusick char *name;
10822840Smckusick {
10922840Smckusick nincl = 0;
11022840Smckusick inclp = NULL;
11122840Smckusick doinclude(name);
11222840Smckusick lexstate = NEWSTMT;
11322840Smckusick return(NO);
11422840Smckusick }
11522840Smckusick 
11622840Smckusick 
11722840Smckusick 
11822840Smckusick /* throw away the rest of the current line */
flline()11922840Smckusick flline()
12022840Smckusick {
12122840Smckusick lexstate = RETEOS;
12222840Smckusick }
12322840Smckusick 
12422840Smckusick 
12522840Smckusick 
lexline(n)12622840Smckusick char *lexline(n)
12722840Smckusick int *n;
12822840Smckusick {
12922840Smckusick *n = (lastch - nextch) + 1;
13022840Smckusick return(nextch);
13122840Smckusick }
13222840Smckusick 
13322840Smckusick 
13422840Smckusick 
13522840Smckusick 
13622840Smckusick 
doinclude(name)13722840Smckusick doinclude(name)
13822840Smckusick char *name;
13922840Smckusick {
14022840Smckusick FILEP fp;
14122840Smckusick struct Inclfile *t;
14222840Smckusick char temp[100];
14322840Smckusick register char *lastslash, *s;
14422840Smckusick 
14522840Smckusick if(inclp)
14622840Smckusick 	{
14722840Smckusick 	inclp->incllno = thislin;
14822840Smckusick 	inclp->inclcode = code;
14922840Smckusick 	inclp->inclstno = nxtstno;
15022840Smckusick 	if(nextcd)
15122840Smckusick 		inclp->incllinp = copyn(inclp->incllen = endcd-nextcd , nextcd);
15222840Smckusick 	else
15322840Smckusick 		inclp->incllinp = 0;
15422840Smckusick 	}
15522840Smckusick nextcd = NULL;
15622840Smckusick 
15722840Smckusick if(++nincl >= MAXINCLUDES)
15822840Smckusick 	fatal("includes nested too deep");
15922840Smckusick if(name[0] == '\0')
16022840Smckusick 	fp = stdin;
16122840Smckusick else if(name[0]=='/' || inclp==NULL)
16222840Smckusick 	fp = fopen(name, "r");
16322840Smckusick else	{
16422840Smckusick 	lastslash = NULL;
16522840Smckusick 	for(s = inclp->inclname ; *s ; ++s)
16622840Smckusick 		if(*s == '/')
16722840Smckusick 			lastslash = s;
16822840Smckusick 	if(lastslash)
16922840Smckusick 		{
17022840Smckusick 		*lastslash = '\0';
17122840Smckusick 		sprintf(temp, "%s/%s", inclp->inclname, name);
17222840Smckusick 		*lastslash = '/';
17322840Smckusick 		}
17422840Smckusick 	else
17522840Smckusick 		strcpy(temp, name);
17622840Smckusick 
17722840Smckusick 	if( (fp = fopen(temp, "r")) == NULL )
17822840Smckusick 		{
17937795Sbostic 		sprintf(temp, "%s/%s", _PATH_INCLUDES, name);
18022840Smckusick 		fp = fopen(temp, "r");
18122840Smckusick 		}
18222840Smckusick 	if(fp)
18322840Smckusick 		name = copys(temp);
18422840Smckusick 	}
18522840Smckusick 
18622840Smckusick if( fp )
18722840Smckusick 	{
18822840Smckusick 	t = inclp;
18922840Smckusick 	inclp = ALLOC(Inclfile);
19022840Smckusick 	inclp->inclnext = t;
19122840Smckusick 	prevlin = thislin = 0;
19222840Smckusick 	inclp->inclname = name;
19322840Smckusick 	infname = copys(name);
19422840Smckusick 	infile = inclp->inclfp = fp;
19522840Smckusick 	}
19622840Smckusick else
19722840Smckusick 	{
19822840Smckusick 	fprintf(diagfile, "Cannot open file %s", name);
19922840Smckusick 	done(1);
20022840Smckusick 	}
20122840Smckusick }
20222840Smckusick 
20322840Smckusick 
20422840Smckusick 
20522840Smckusick 
popinclude()20622840Smckusick LOCAL popinclude()
20722840Smckusick {
20822840Smckusick struct Inclfile *t;
20922840Smckusick register char *p;
21022840Smckusick register int k;
21122840Smckusick 
21222840Smckusick if(infile != stdin)
21322840Smckusick 	clf(&infile);
21422840Smckusick free(infname);
21522840Smckusick 
21622840Smckusick --nincl;
21722840Smckusick t = inclp->inclnext;
21822840Smckusick free(inclp->inclname);
21922840Smckusick free( (charptr) inclp);
22022840Smckusick inclp = t;
22122840Smckusick if(inclp == NULL)
22222840Smckusick 	return(NO);
22322840Smckusick 
22422840Smckusick infile = inclp->inclfp;
22522840Smckusick infname = copys(inclp->inclname);
22622840Smckusick prevlin = thislin = inclp->incllno;
22722840Smckusick code = inclp->inclcode;
22822840Smckusick stno = nxtstno = inclp->inclstno;
22922840Smckusick if(inclp->incllinp)
23022840Smckusick 	{
23122840Smckusick 	endcd = nextcd = s;
23222840Smckusick 	k = inclp->incllen;
23322840Smckusick 	p = inclp->incllinp;
23422840Smckusick 	while(--k >= 0)
23522840Smckusick 		*endcd++ = *p++;
23622840Smckusick 	free( (charptr) (inclp->incllinp) );
23722840Smckusick 	}
23822840Smckusick else
23922840Smckusick 	nextcd = NULL;
24022840Smckusick return(YES);
24122840Smckusick }
24222840Smckusick 
24322840Smckusick 
24422840Smckusick 
24522840Smckusick 
yylex()24622840Smckusick yylex()
24722840Smckusick {
24822840Smckusick static int  tokno;
24922840Smckusick 
25022840Smckusick 	switch(lexstate)
25122840Smckusick 	{
25222840Smckusick case NEWSTMT :	/* need a new statement */
25322840Smckusick 	if(getcds() == STEOF)
25422840Smckusick 		return(SEOF);
25522840Smckusick 	lastend =  stkey == SEND;
25622840Smckusick 	crunch();
25722840Smckusick 	tokno = 0;
25822840Smckusick 	lexstate = FIRSTTOKEN;
25922840Smckusick 	yystno = stno;
26022840Smckusick 	stno = nxtstno;
26122840Smckusick 	toklen = 0;
26222840Smckusick 	return(SLABEL);
26322840Smckusick 
26422840Smckusick first:
26522840Smckusick case FIRSTTOKEN :	/* first step on a statement */
26622840Smckusick 	analyz();
26722840Smckusick 	lexstate = OTHERTOKEN;
26822840Smckusick 	tokno = 1;
26922840Smckusick 	return(stkey);
27022840Smckusick 
27122840Smckusick case OTHERTOKEN :	/* return next token */
27222840Smckusick 	if(nextch > lastch)
27322840Smckusick 		goto reteos;
27422840Smckusick 	++tokno;
27522840Smckusick 	if( (stkey==SLOGIF || stkey==SELSEIF) && parlev==0 && tokno>3)
27622840Smckusick 		goto first;
27722840Smckusick 
27822840Smckusick 	if(stkey==SASSIGN && tokno==3 && nextch<lastch &&
27922840Smckusick 		nextch[0]=='t' && nextch[1]=='o')
28022840Smckusick 			{
28122840Smckusick 			nextch+=2;
28222840Smckusick 			return(STO);
28322840Smckusick 			}
28422840Smckusick 	return(gettok());
28522840Smckusick 
28622840Smckusick reteos:
28722840Smckusick case RETEOS:
28822840Smckusick 	lexstate = NEWSTMT;
28922840Smckusick 	return(SEOS);
29022840Smckusick 	}
29122840Smckusick fatali("impossible lexstate %d", lexstate);
29222840Smckusick /* NOTREACHED */
29322840Smckusick }
29422840Smckusick 
getcds()29522840Smckusick LOCAL getcds()
29622840Smckusick {
29722840Smckusick register char *p, *q;
29822840Smckusick 
29922840Smckusick 	if (newname)
30022840Smckusick 		{
30122840Smckusick 		free(infname);
30222840Smckusick 		infname = newname;
30322840Smckusick 		newname = NULL;
30422840Smckusick 		}
30522840Smckusick 
30622840Smckusick top:
30722840Smckusick 	if(nextcd == NULL)
30822840Smckusick 		{
30922840Smckusick 		code = getcd( nextcd = s );
31022840Smckusick 		stno = nxtstno;
31122840Smckusick 		if (newname)
31222840Smckusick 			{
31322840Smckusick 			free(infname);
31422840Smckusick 			infname = newname;
31522840Smckusick 			newname = NULL;
31622840Smckusick 			}
31722840Smckusick 		prevlin = thislin;
31822840Smckusick 		}
31922840Smckusick 	if(code == STEOF)
32022840Smckusick 		if( popinclude() )
32122840Smckusick 			goto top;
32222840Smckusick 		else
32322840Smckusick 			return(STEOF);
32422840Smckusick 
32522840Smckusick 	if(code == STCONTINUE)
32622840Smckusick 		{
32722840Smckusick 		if (newname)
32822840Smckusick 			{
32922840Smckusick 			free(infname);
33022840Smckusick 			infname = newname;
33122840Smckusick 			newname = NULL;
33222840Smckusick 			}
33322840Smckusick 		lineno = thislin;
33422840Smckusick 		err("illegal continuation card ignored");
33522840Smckusick 		nextcd = NULL;
33622840Smckusick 		goto top;
33722840Smckusick 		}
33822840Smckusick 
33922840Smckusick 	if(nextcd > s)
34022840Smckusick 		{
34122840Smckusick 		q = nextcd;
34222840Smckusick 		p = s;
34322840Smckusick 		while(q < endcd)
34422840Smckusick 			*p++ = *q++;
34522840Smckusick 		endcd = p;
34622840Smckusick 		}
34722840Smckusick 	for(nextcd = endcd ;
34822840Smckusick 		nextcd+66<=send && (code = getcd(nextcd))==STCONTINUE ;
34922840Smckusick 		nextcd = endcd )
35022840Smckusick 			;
35122840Smckusick 	nextch = s;
35222840Smckusick 	lastch = nextcd - 1;
35322840Smckusick 	if(nextcd >= send)
35422840Smckusick 		nextcd = NULL;
35522840Smckusick 	lineno = prevlin;
35622840Smckusick 	prevlin = thislin;
35722840Smckusick 	return(STINITIAL);
35822840Smckusick }
35922840Smckusick 
getcd(b)36022840Smckusick LOCAL getcd(b)
36122840Smckusick register char *b;
36222840Smckusick {
36322840Smckusick register int c;
36422840Smckusick register char *p, *bend;
36522840Smckusick int speclin;
36622840Smckusick static char a[6];
36722840Smckusick static char *aend	= a+6;
36822840Smckusick int num;
36922840Smckusick 
37022840Smckusick top:
37122840Smckusick 	endcd = b;
37222840Smckusick 	bend = b+66;
37322840Smckusick 	speclin = NO;
37422840Smckusick 
37522840Smckusick 	if( (c = getc(infile)) == '&')
37622840Smckusick 		{
37722840Smckusick 		a[0] = BLANK;
37822840Smckusick 		a[5] = 'x';
37922840Smckusick 		speclin = YES;
38022840Smckusick 		bend = send;
38122840Smckusick 		}
38222840Smckusick 	else if(c=='c' || c=='C' || c=='*')
38322840Smckusick 		{
38422840Smckusick 		while( (c = getc(infile)) != '\n')
38522840Smckusick 			if(c == EOF)
38622840Smckusick 				return(STEOF);
38722840Smckusick 		++thislin;
38822840Smckusick 		goto top;
38922840Smckusick 		}
39022840Smckusick 	else if(c == '#')
39122840Smckusick 		{
39222840Smckusick 		c = getc(infile);
39322840Smckusick 		while (c == BLANK || c == '\t')
39422840Smckusick 			c = getc(infile);
39522840Smckusick 
39622840Smckusick 		num = 0;
39722840Smckusick 		while (isdigit(c))
39822840Smckusick 			{
39922840Smckusick 			num = 10*num + c - '0';
40022840Smckusick 			c = getc(infile);
40122840Smckusick 			}
40222840Smckusick 		thislin = num - 1;
40322840Smckusick 
40422840Smckusick 		while (c == BLANK || c == '\t')
40522840Smckusick 			c = getc(infile);
40622840Smckusick 
40722840Smckusick 		if (c == '"')
40822840Smckusick 			{
40922840Smckusick 			char fname[1024];
41022840Smckusick 			int len = 0;
41122840Smckusick 
41222840Smckusick 			c = getc(infile);
41322840Smckusick 			while (c != '"' && c != '\n')
41422840Smckusick 				{
41522840Smckusick 				fname[len++] = c;
41622840Smckusick 				c = getc(infile);
41722840Smckusick 				}
41822840Smckusick 			fname[len++] = '\0';
41922840Smckusick 
42022840Smckusick 			if (newname)
42122840Smckusick 				free(newname);
42222840Smckusick 			newname = (char *) ckalloc(len);
42322840Smckusick 			strcpy(newname, fname);
42422840Smckusick 			}
42522840Smckusick 
42622840Smckusick 		while (c != '\n')
42722840Smckusick 			if (c == EOF)
42822840Smckusick 				return (STEOF);
42922840Smckusick 			else
43022840Smckusick 				c = getc(infile);
43122840Smckusick 		goto top;
43222840Smckusick 		}
43322840Smckusick 
43422840Smckusick 	else if(c != EOF)
43522840Smckusick 		{
43622840Smckusick 		/* a tab in columns 1-6 skips to column 7 */
43722840Smckusick 		ungetc(c, infile);
43822840Smckusick 		for(p=a; p<aend && (c=getc(infile)) != '\n' && c!=EOF; )
43922840Smckusick 			if(c == '\t')
44022840Smckusick 				{
44122840Smckusick 				while(p < aend)
44222840Smckusick 					*p++ = BLANK;
44322840Smckusick 				speclin = YES;
44422840Smckusick 				bend = send;
44522840Smckusick 				}
44622840Smckusick 			else
44722840Smckusick 				*p++ = c;
44822840Smckusick 		}
44922840Smckusick 	if(c == EOF)
45022840Smckusick 		return(STEOF);
45122840Smckusick 	if(c == '\n')
45222840Smckusick 		{
45322840Smckusick 		while(p < aend)
45422840Smckusick 			*p++ = BLANK;
45522840Smckusick 		if( ! speclin )
45622840Smckusick 			while(endcd < bend)
45722840Smckusick 				*endcd++ = BLANK;
45822840Smckusick 		}
45922840Smckusick 	else	{	/* read body of line */
46022840Smckusick 		while( endcd<bend && (c=getc(infile)) != '\n' && c!=EOF )
46122840Smckusick 			*endcd++ = c;
46222840Smckusick 		if(c == EOF)
46322840Smckusick 			return(STEOF);
46422840Smckusick 		if(c != '\n')
46522840Smckusick 			{
46622840Smckusick 			while( (c=getc(infile)) != '\n')
46722840Smckusick 				if(c == EOF)
46822840Smckusick 					return(STEOF);
46922840Smckusick 			}
47022840Smckusick 
47122840Smckusick 		if( ! speclin )
47222840Smckusick 			while(endcd < bend)
47322840Smckusick 				*endcd++ = BLANK;
47422840Smckusick 		}
47522840Smckusick 	++thislin;
47622840Smckusick 	if( !isspace(a[5]) && a[5]!='0')
47722840Smckusick 		return(STCONTINUE);
47822840Smckusick 	for(p=a; p<aend; ++p)
47922840Smckusick 		if( !isspace(*p) ) goto initline;
48022840Smckusick 	for(p = b ; p<endcd ; ++p)
48122840Smckusick 		if( !isspace(*p) ) goto initline;
48222840Smckusick 	goto top;
48322840Smckusick 
48422840Smckusick initline:
48522840Smckusick 	nxtstno = 0;
48622840Smckusick 	for(p = a ; p<a+5 ; ++p)
48722840Smckusick 		if( !isspace(*p) )
48822840Smckusick 			if(isdigit(*p))
48922840Smckusick 				nxtstno = 10*nxtstno + (*p - '0');
49022840Smckusick 			else	{
49122840Smckusick 				if (newname)
49222840Smckusick 					{
49322840Smckusick 					free(infname);
49422840Smckusick 					infname = newname;
49522840Smckusick 					newname = NULL;
49622840Smckusick 					}
49722840Smckusick 				lineno = thislin;
49822840Smckusick 				err("nondigit in statement number field");
49922840Smckusick 				nxtstno = 0;
50022840Smckusick 				break;
50122840Smckusick 				}
50222840Smckusick 	return(STINITIAL);
50322840Smckusick }
50422840Smckusick 
crunch()50522840Smckusick LOCAL crunch()
50622840Smckusick {
50722840Smckusick register char *i, *j, *j0, *j1, *prvstr;
50822840Smckusick int ten, nh, quote;
50922840Smckusick 
51022840Smckusick /* i is the next input character to be looked at
51122840Smckusick j is the next output character */
51222840Smckusick parlev = 0;
51322840Smckusick expcom = 0;	/* exposed ','s */
51422840Smckusick expeql = 0;	/* exposed equal signs */
51522840Smckusick j = s;
51622840Smckusick prvstr = s;
51722840Smckusick for(i=s ; i<=lastch ; ++i)
51822840Smckusick 	{
51922840Smckusick 	if(isspace(*i) )
52022840Smckusick 		continue;
52122840Smckusick 	if(*i=='\'' ||  *i=='"')
52222840Smckusick 		{
52322840Smckusick 		quote = *i;
52422840Smckusick 		*j = MYQUOTE; /* special marker */
52522840Smckusick 		for(;;)
52622840Smckusick 			{
52722840Smckusick 			if(++i > lastch)
52822840Smckusick 				{
52922840Smckusick 				err("unbalanced quotes; closing quote supplied");
53022840Smckusick 				break;
53122840Smckusick 				}
53222840Smckusick 			if(*i == quote)
53322840Smckusick 				if(i<lastch && i[1]==quote) ++i;
53422840Smckusick 				else break;
53522840Smckusick 			else if(*i=='\\' && i<lastch)
53622840Smckusick 				switch(*++i)
53722840Smckusick 					{
53822840Smckusick 					case 't':
53922840Smckusick 						*i = '\t'; break;
54022840Smckusick 					case 'b':
54122840Smckusick 						*i = '\b'; break;
54222840Smckusick 					case 'n':
54322840Smckusick 						*i = '\n'; break;
54422840Smckusick 					case 'f':
54522840Smckusick 						*i = '\f'; break;
54622840Smckusick 					case 'v':
54722840Smckusick 						*i = '\v'; break;
54822840Smckusick 					case '0':
54922840Smckusick 						*i = '\0'; break;
55022840Smckusick 					default:
55122840Smckusick 						break;
55222840Smckusick 					}
55322840Smckusick 			*++j = *i;
55422840Smckusick 			}
55522840Smckusick 		j[1] = MYQUOTE;
55622840Smckusick 		j += 2;
55722840Smckusick 		prvstr = j;
55822840Smckusick 		}
55922840Smckusick 	else if( (*i=='h' || *i=='H')  && j>prvstr)	/* test for Hollerith strings */
56022840Smckusick 		{
56122840Smckusick 		if( ! isdigit(j[-1])) goto copychar;
56222840Smckusick 		nh = j[-1] - '0';
56322840Smckusick 		ten = 10;
56422840Smckusick 		j1 = prvstr - 1;
56522840Smckusick 		if (j1<j-5) j1=j-5;
56622840Smckusick 		for(j0=j-2 ; j0>j1; -- j0)
56722840Smckusick 			{
56822840Smckusick 			if( ! isdigit(*j0 ) ) break;
56922840Smckusick 			nh += ten * (*j0-'0');
57022840Smckusick 			ten*=10;
57122840Smckusick 			}
57222840Smckusick 		if(j0 <= j1) goto copychar;
57322840Smckusick /* a hollerith must be preceded by a punctuation mark.
57422840Smckusick    '*' is possible only as repetition factor in a data statement
57522840Smckusick    not, in particular, in character*2h
57622840Smckusick */
57722840Smckusick 
57822840Smckusick 		if( !(*j0=='*'&&s[0]=='d') && *j0!='/' && *j0!='(' &&
57922840Smckusick 			*j0!=',' && *j0!='=' && *j0!='.')
58022840Smckusick 				goto copychar;
58122840Smckusick 		if(i+nh > lastch)
58222840Smckusick 			{
58322840Smckusick 			erri("%dH too big", nh);
58422840Smckusick 			nh = lastch - i;
58522840Smckusick 			}
58622840Smckusick 		j0[1] = MYQUOTE; /* special marker */
58722840Smckusick 		j = j0 + 1;
58822840Smckusick 		while(nh-- > 0)
58922840Smckusick 			{
59022840Smckusick 			if(*++i == '\\')
59122840Smckusick 				switch(*++i)
59222840Smckusick 					{
59322840Smckusick 					case 't':
59422840Smckusick 						*i = '\t'; break;
59522840Smckusick 					case 'b':
59622840Smckusick 						*i = '\b'; break;
59722840Smckusick 					case 'n':
59822840Smckusick 						*i = '\n'; break;
59922840Smckusick 					case 'f':
60022840Smckusick 						*i = '\f'; break;
60122840Smckusick 					case '0':
60222840Smckusick 						*i = '\0'; break;
60322840Smckusick 					default:
60422840Smckusick 						break;
60522840Smckusick 					}
60622840Smckusick 			*++j = *i;
60722840Smckusick 			}
60822840Smckusick 		j[1] = MYQUOTE;
60922840Smckusick 		j+=2;
61022840Smckusick 		prvstr = j;
61122840Smckusick 		}
61222840Smckusick 	else	{
61322840Smckusick 		if(*i == '(') ++parlev;
61422840Smckusick 		else if(*i == ')') --parlev;
61522840Smckusick 		else if(parlev == 0)
61622840Smckusick 			if(*i == '=') expeql = 1;
61722840Smckusick 			else if(*i == ',') expcom = 1;
61822840Smckusick copychar:		/*not a string or space -- copy, shifting case if necessary */
61922840Smckusick 		if(shiftcase && isupper(*i))
62022840Smckusick 			*j++ = tolower(*i);
62122840Smckusick 		else	*j++ = *i;
62222840Smckusick 		}
62322840Smckusick 	}
62422840Smckusick lastch = j - 1;
62522840Smckusick nextch = s;
62622840Smckusick }
62722840Smckusick 
analyz()62822840Smckusick LOCAL analyz()
62922840Smckusick {
63022840Smckusick register char *i;
63122840Smckusick 
63222840Smckusick 	if(parlev != 0)
63322840Smckusick 		{
63422840Smckusick 		err("unbalanced parentheses, statement skipped");
63522840Smckusick 		stkey = SUNKNOWN;
63622840Smckusick 		return;
63722840Smckusick 		}
63822840Smckusick 	if(nextch+2<=lastch && nextch[0]=='i' && nextch[1]=='f' && nextch[2]=='(')
63922840Smckusick 		{
64022840Smckusick /* assignment or if statement -- look at character after balancing paren */
64122840Smckusick 		parlev = 1;
64222840Smckusick 		for(i=nextch+3 ; i<=lastch; ++i)
64322840Smckusick 			if(*i == (MYQUOTE))
64422840Smckusick 				{
64522840Smckusick 				while(*++i != MYQUOTE)
64622840Smckusick 					;
64722840Smckusick 				}
64822840Smckusick 			else if(*i == '(')
64922840Smckusick 				++parlev;
65022840Smckusick 			else if(*i == ')')
65122840Smckusick 				{
65222840Smckusick 				if(--parlev == 0)
65322840Smckusick 					break;
65422840Smckusick 				}
65522840Smckusick 		if(i >= lastch)
65622840Smckusick 			stkey = SLOGIF;
65722840Smckusick 		else if(i[1] == '=')
65822840Smckusick 			stkey = SLET;
65922840Smckusick 		else if( isdigit(i[1]) )
66022840Smckusick 			stkey = SARITHIF;
66122840Smckusick 		else	stkey = SLOGIF;
66222840Smckusick 		if(stkey != SLET)
66322840Smckusick 			nextch += 2;
66422840Smckusick 		}
66522840Smckusick 	else if(expeql) /* may be an assignment */
66622840Smckusick 		{
66722840Smckusick 		if(expcom && nextch<lastch &&
66822840Smckusick 			nextch[0]=='d' && nextch[1]=='o')
66922840Smckusick 				{
67022840Smckusick 				stkey = SDO;
67122840Smckusick 				nextch += 2;
67222840Smckusick 				}
67322840Smckusick 		else	stkey = SLET;
67422840Smckusick 		}
67522840Smckusick /* otherwise search for keyword */
67622840Smckusick 	else	{
67722840Smckusick 		stkey = getkwd();
67822840Smckusick 		if(stkey==SGOTO && lastch>=nextch)
67922840Smckusick 			if(nextch[0]=='(')
68022840Smckusick 				stkey = SCOMPGOTO;
68122840Smckusick 			else if(isalpha(nextch[0]))
68222840Smckusick 				stkey = SASGOTO;
68322840Smckusick 		}
68422840Smckusick 	parlev = 0;
68522840Smckusick }
68622840Smckusick 
68722840Smckusick 
68822840Smckusick 
getkwd()68922840Smckusick LOCAL getkwd()
69022840Smckusick {
69122840Smckusick register char *i, *j;
69222840Smckusick register struct Keylist *pk, *pend;
69322840Smckusick int k;
69422840Smckusick 
69522840Smckusick if(! isalpha(nextch[0]) )
69622840Smckusick 	return(SUNKNOWN);
69722840Smckusick k = nextch[0] - 'a';
69822840Smckusick if(pk = keystart[k])
69922840Smckusick 	for(pend = keyend[k] ; pk<=pend ; ++pk )
70022840Smckusick 		{
70122840Smckusick 		i = pk->keyname;
70222840Smckusick 		j = nextch;
70322840Smckusick 		while(*++i==*++j && *i!='\0')
70422840Smckusick 			;
70522840Smckusick 		if(*i=='\0' && j<=lastch+1)
70622840Smckusick 			{
70722840Smckusick 			nextch = j;
70824481Sdonn #ifdef ONLY66
70922840Smckusick 			if(no66flag && pk->notinf66)
71022840Smckusick 				errstr("Not a Fortran 66 keyword: %s",
71122840Smckusick 					pk->keyname);
71224481Sdonn #endif
71322840Smckusick 			return(pk->keyval);
71422840Smckusick 			}
71522840Smckusick 		}
71622840Smckusick return(SUNKNOWN);
71722840Smckusick }
71822840Smckusick 
71922840Smckusick 
72022840Smckusick 
initkey()72122840Smckusick initkey()
72222840Smckusick {
72322840Smckusick extern struct Keylist keys[];
72422840Smckusick register struct Keylist *p;
72522840Smckusick register int i,j;
72622840Smckusick 
72722840Smckusick for(i = 0 ; i<26 ; ++i)
72822840Smckusick 	keystart[i] = NULL;
72922840Smckusick 
73022840Smckusick for(p = keys ; p->keyname ; ++p)
73122840Smckusick 	{
73222840Smckusick 	j = p->keyname[0] - 'a';
73322840Smckusick 	if(keystart[j] == NULL)
73422840Smckusick 		keystart[j] = p;
73522840Smckusick 	keyend[j] = p;
73622840Smckusick 	}
73722840Smckusick }
73822840Smckusick 
gettok()73922840Smckusick LOCAL gettok()
74022840Smckusick {
74122840Smckusick int havdot, havexp, havdbl;
74222840Smckusick int radix, val;
74322840Smckusick extern struct Punctlist puncts[];
74422840Smckusick struct Punctlist *pp;
74522840Smckusick extern struct Fmtlist fmts[];
74622840Smckusick extern struct Dotlist dots[];
74722840Smckusick struct Dotlist *pd;
74822840Smckusick 
74922840Smckusick char *i, *j, *n1, *p;
75022840Smckusick 
75122840Smckusick 	if(*nextch == (MYQUOTE))
75222840Smckusick 		{
75322840Smckusick 		++nextch;
75422840Smckusick 		p = token;
75525742Sdonn 		while(nextch <= lastch && *nextch != MYQUOTE)
75622840Smckusick 			*p++ = *nextch++;
75722840Smckusick 		++nextch;
75822840Smckusick 		toklen = p - token;
75922840Smckusick 		*p = '\0';
76022840Smckusick 		return (SHOLLERITH);
76122840Smckusick 		}
76222840Smckusick /*
76322840Smckusick 	if(stkey == SFORMAT)
76422840Smckusick 		{
76522840Smckusick 		for(pf = fmts; pf->fmtchar; ++pf)
76622840Smckusick 			{
76722840Smckusick 			if(*nextch == pf->fmtchar)
76822840Smckusick 				{
76922840Smckusick 				++nextch;
77022840Smckusick 				if(pf->fmtval == SLPAR)
77122840Smckusick 					++parlev;
77222840Smckusick 				else if(pf->fmtval == SRPAR)
77322840Smckusick 					--parlev;
77422840Smckusick 				return(pf->fmtval);
77522840Smckusick 				}
77622840Smckusick 			}
77722840Smckusick 		if( isdigit(*nextch) )
77822840Smckusick 			{
77922840Smckusick 			p = token;
78022840Smckusick 			*p++ = *nextch++;
78122840Smckusick 			while(nextch<=lastch && isdigit(*nextch) )
78222840Smckusick 				*p++ = *nextch++;
78322840Smckusick 			toklen = p - token;
78422840Smckusick 			*p = '\0';
78522840Smckusick 			if(nextch<=lastch && *nextch=='p')
78622840Smckusick 				{
78722840Smckusick 				++nextch;
78822840Smckusick 				return(SSCALE);
78922840Smckusick 				}
79022840Smckusick 			else	return(SICON);
79122840Smckusick 			}
79222840Smckusick 		if( isalpha(*nextch) )
79322840Smckusick 			{
79422840Smckusick 			p = token;
79522840Smckusick 			*p++ = *nextch++;
79622840Smckusick 			while(nextch<=lastch &&
79722840Smckusick 				(*nextch=='.' || isdigit(*nextch) || isalpha(*nextch) ))
79822840Smckusick 					*p++ = *nextch++;
79922840Smckusick 			toklen = p - token;
80022840Smckusick 			*p = '\0';
80122840Smckusick 			return(SFIELD);
80222840Smckusick 			}
80322840Smckusick 		goto badchar;
80422840Smckusick 		}
80522840Smckusick /* Not a format statement */
80622840Smckusick 
80722840Smckusick if(needkwd)
80822840Smckusick 	{
80922840Smckusick 	needkwd = 0;
81022840Smckusick 	return( getkwd() );
81122840Smckusick 	}
81222840Smckusick 
81322840Smckusick 	for(pp=puncts; pp->punchar; ++pp)
81422840Smckusick 		if(*nextch == pp->punchar)
81522840Smckusick 			{
81622840Smckusick 			if( (*nextch=='*' || *nextch=='/') &&
81722840Smckusick 				nextch<lastch && nextch[1]==nextch[0])
81822840Smckusick 					{
81922840Smckusick 					if(*nextch == '*')
82022840Smckusick 						val = SPOWER;
82122840Smckusick 					else	val = SCONCAT;
82222840Smckusick 					nextch+=2;
82322840Smckusick 					}
82422840Smckusick 			else	{
82522840Smckusick 				val = pp->punval;
82622840Smckusick 				if(val==SLPAR)
82722840Smckusick 					++parlev;
82822840Smckusick 				else if(val==SRPAR)
82922840Smckusick 					--parlev;
83022840Smckusick 				++nextch;
83122840Smckusick 				}
83222840Smckusick 			return(val);
83322840Smckusick 			}
83422840Smckusick 	if(*nextch == '.')
83522840Smckusick 		if(nextch >= lastch) goto badchar;
83622840Smckusick 		else if(isdigit(nextch[1])) goto numconst;
83722840Smckusick 		else	{
83822840Smckusick 			for(pd=dots ; (j=pd->dotname) ; ++pd)
83922840Smckusick 				{
84022840Smckusick 				for(i=nextch+1 ; i<=lastch ; ++i)
84122840Smckusick 					if(*i != *j) break;
84222840Smckusick 					else if(*i != '.') ++j;
84322840Smckusick 					else	{
84422840Smckusick 						nextch = i+1;
84522840Smckusick 						return(pd->dotval);
84622840Smckusick 						}
84722840Smckusick 				}
84822840Smckusick 			goto badchar;
84922840Smckusick 			}
85022840Smckusick 	if( isalpha(*nextch) )
85122840Smckusick 		{
85222840Smckusick 		p = token;
85322840Smckusick 		*p++ = *nextch++;
85422840Smckusick 		while(nextch<=lastch)
85522840Smckusick 			if( isalpha(*nextch) || isdigit(*nextch) )
85622840Smckusick 				*p++ = *nextch++;
85722840Smckusick 			else break;
85822840Smckusick 		toklen = p - token;
85922840Smckusick 		*p = '\0';
86022840Smckusick 		if(inioctl && nextch<=lastch && *nextch=='=')
86122840Smckusick 			{
86222840Smckusick 			++nextch;
86322840Smckusick 			return(SNAMEEQ);
86422840Smckusick 			}
86522840Smckusick 		if(toklen>8 && eqn(8,token,"function") && isalpha(token[8]) &&
86622840Smckusick 			nextch<lastch && nextch[0]=='(' &&
86722840Smckusick 			(nextch[1]==')' | isalpha(nextch[1])) )
86822840Smckusick 				{
86922840Smckusick 				nextch -= (toklen - 8);
87022840Smckusick 				return(SFUNCTION);
87122840Smckusick 				}
87222840Smckusick 		if(toklen > VL)
87322840Smckusick 			{
87422840Smckusick 			char buff[30];
87522840Smckusick 			sprintf(buff, "name %s too long, truncated to %d",
87622840Smckusick 				token, VL);
87722840Smckusick 			err(buff);
87822840Smckusick 			toklen = VL;
87922840Smckusick 			token[VL] = '\0';
88022840Smckusick 			}
88122840Smckusick 		if(toklen==1 && *nextch==MYQUOTE)
88222840Smckusick 			{
88322840Smckusick 			switch(token[0])
88422840Smckusick 				{
88522840Smckusick 				case 'z':  case 'Z':
88622840Smckusick 				case 'x':  case 'X':
88722840Smckusick 					radix = 16; break;
88822840Smckusick 				case 'o':  case 'O':
88922840Smckusick 					radix = 8; break;
89022840Smckusick 				case 'b':  case 'B':
89122840Smckusick 					radix = 2; break;
89222840Smckusick 				default:
89322840Smckusick 					err("bad bit identifier");
89422840Smckusick 					return(SNAME);
89522840Smckusick 				}
89622840Smckusick 			++nextch;
89722840Smckusick 			for(p = token ; *nextch!=MYQUOTE ; )
89822840Smckusick 				if ( *nextch == BLANK || *nextch == '\t')
89922840Smckusick 					nextch++;
90022840Smckusick 				else
90122840Smckusick 					{
90222840Smckusick 					if (isupper(*nextch))
90322840Smckusick 						*nextch = tolower(*nextch);
90422840Smckusick 					if (hextoi(*p++ = *nextch++) >= radix)
90522840Smckusick 						{
90622840Smckusick 						err("invalid binary character");
90722840Smckusick 						break;
90822840Smckusick 						}
90922840Smckusick 					}
91022840Smckusick 			++nextch;
91122840Smckusick 			toklen = p - token;
91222840Smckusick 			return( radix==16 ? SHEXCON :
91322840Smckusick 				(radix==8 ? SOCTCON : SBITCON) );
91422840Smckusick 			}
91522840Smckusick 		return(SNAME);
91622840Smckusick 		}
91722840Smckusick 	if( ! isdigit(*nextch) ) goto badchar;
91822840Smckusick numconst:
91922840Smckusick 	havdot = NO;
92022840Smckusick 	havexp = NO;
92122840Smckusick 	havdbl = NO;
92222840Smckusick 	for(n1 = nextch ; nextch<=lastch ; ++nextch)
92322840Smckusick 		{
92422840Smckusick 		if(*nextch == '.')
92522840Smckusick 			if(havdot) break;
92622840Smckusick 			else if(nextch+2<=lastch && isalpha(nextch[1])
92722840Smckusick 				&& isalpha(nextch[2]))
92822840Smckusick 					break;
92922840Smckusick 			else	havdot = YES;
93022840Smckusick 		else if( !intonly && (*nextch=='d' || *nextch=='e') )
93122840Smckusick 			{
93222840Smckusick 			p = nextch;
93322840Smckusick 			havexp = YES;
93422840Smckusick 			if(*nextch == 'd')
93522840Smckusick 				havdbl = YES;
93622840Smckusick 			if(nextch<lastch)
93722840Smckusick 				if(nextch[1]=='+' || nextch[1]=='-')
93822840Smckusick 					++nextch;
93922840Smckusick 			if( (nextch >= lastch) || ! isdigit(*++nextch) )
94022840Smckusick 				{
94122840Smckusick 				nextch = p;
94222840Smckusick 				havdbl = havexp = NO;
94322840Smckusick 				break;
94422840Smckusick 				}
94522840Smckusick 			for(++nextch ;
94622840Smckusick 				nextch<=lastch && isdigit(*nextch);
94722840Smckusick 				++nextch);
94822840Smckusick 			break;
94922840Smckusick 			}
95022840Smckusick 		else if( ! isdigit(*nextch) )
95122840Smckusick 			break;
95222840Smckusick 		}
95322840Smckusick 	p = token;
95422840Smckusick 	i = n1;
95522840Smckusick 	while(i < nextch)
95622840Smckusick 		*p++ = *i++;
95722840Smckusick 	toklen = p - token;
95822840Smckusick 	*p = '\0';
95922840Smckusick 	if(havdbl) return(SDCON);
96024481Sdonn 	if(havdot || havexp) return( dblflag ? SDCON : SRCON);
96122840Smckusick 	return(SICON);
96222840Smckusick badchar:
96322840Smckusick 	s[0] = *nextch++;
96422840Smckusick 	return(SUNKNOWN);
96522840Smckusick }
96622840Smckusick 
96722840Smckusick /* KEYWORD AND SPECIAL CHARACTER TABLES
96822840Smckusick */
96922840Smckusick 
97022840Smckusick struct Punctlist puncts[ ] =
97122840Smckusick 	{
97222840Smckusick 	'(', SLPAR,
97322840Smckusick 	')', SRPAR,
97422840Smckusick 	'=', SEQUALS,
97522840Smckusick 	',', SCOMMA,
97622840Smckusick 	'+', SPLUS,
97722840Smckusick 	'-', SMINUS,
97822840Smckusick 	'*', SSTAR,
97922840Smckusick 	'/', SSLASH,
98022840Smckusick 	'$', SCURRENCY,
98122840Smckusick 	':', SCOLON,
98222840Smckusick 	0, 0 } ;
98322840Smckusick 
98422840Smckusick /*
98522840Smckusick LOCAL struct Fmtlist  fmts[ ] =
98622840Smckusick 	{
98722840Smckusick 	'(', SLPAR,
98822840Smckusick 	')', SRPAR,
98922840Smckusick 	'/', SSLASH,
99022840Smckusick 	',', SCOMMA,
99122840Smckusick 	'-', SMINUS,
99222840Smckusick 	':', SCOLON,
99322840Smckusick 	0, 0 } ;
99422840Smckusick */
99522840Smckusick 
99622840Smckusick LOCAL struct Dotlist  dots[ ] =
99722840Smckusick 	{
99822840Smckusick 	"and.", SAND,
99922840Smckusick 	"or.", SOR,
100022840Smckusick 	"not.", SNOT,
100122840Smckusick 	"true.", STRUE,
100222840Smckusick 	"false.", SFALSE,
100322840Smckusick 	"eq.", SEQ,
100422840Smckusick 	"ne.", SNE,
100522840Smckusick 	"lt.", SLT,
100622840Smckusick 	"le.", SLE,
100722840Smckusick 	"gt.", SGT,
100822840Smckusick 	"ge.", SGE,
100922840Smckusick 	"neqv.", SNEQV,
101022840Smckusick 	"eqv.", SEQV,
101122840Smckusick 	0, 0 } ;
101222840Smckusick 
101322840Smckusick LOCAL struct Keylist  keys[ ] =
101422840Smckusick 	{
101522840Smckusick 	 	{ "assign",  SASSIGN  },
101622840Smckusick 	 	{ "automatic",  SAUTOMATIC, YES  },
101722840Smckusick 	 	{ "backspace",  SBACKSPACE  },
101822840Smckusick 	 	{ "blockdata",  SBLOCK  },
101922840Smckusick 	 	{ "call",  SCALL  },
102022840Smckusick 	 	{ "character",  SCHARACTER, YES  },
102122840Smckusick 	 	{ "close",  SCLOSE, YES  },
102222840Smckusick 	 	{ "common",  SCOMMON  },
102322840Smckusick 	 	{ "complex",  SCOMPLEX  },
102422840Smckusick 	 	{ "continue",  SCONTINUE  },
102522840Smckusick 	 	{ "data",  SDATA  },
102622840Smckusick 	 	{ "dimension",  SDIMENSION  },
102722840Smckusick 	 	{ "doubleprecision",  SDOUBLE  },
102822840Smckusick 	 	{ "doublecomplex", SDCOMPLEX, YES  },
102922840Smckusick 	 	{ "elseif",  SELSEIF, YES  },
103022840Smckusick 	 	{ "else",  SELSE, YES  },
103122840Smckusick 	 	{ "endfile",  SENDFILE  },
103222840Smckusick 	 	{ "endif",  SENDIF, YES  },
103322840Smckusick 	 	{ "end",  SEND  },
103422840Smckusick 	 	{ "entry",  SENTRY, YES  },
103522840Smckusick 	 	{ "equivalence",  SEQUIV  },
103622840Smckusick 	 	{ "external",  SEXTERNAL  },
103722840Smckusick 	 	{ "format",  SFORMAT  },
103822840Smckusick 	 	{ "function",  SFUNCTION  },
103922840Smckusick 	 	{ "goto",  SGOTO  },
104022840Smckusick 	 	{ "implicit",  SIMPLICIT, YES  },
104122840Smckusick 	 	{ "include",  SINCLUDE, YES  },
104222840Smckusick 	 	{ "inquire",  SINQUIRE, YES  },
104322840Smckusick 	 	{ "intrinsic",  SINTRINSIC, YES  },
104422840Smckusick 	 	{ "integer",  SINTEGER  },
104522840Smckusick 	 	{ "logical",  SLOGICAL  },
104622840Smckusick #ifdef NAMELIST
104722840Smckusick 		{ "namelist", SNAMELIST, YES },
104822840Smckusick #endif
104922840Smckusick 		{ "none", SUNDEFINED, YES },
105022840Smckusick 	 	{ "open",  SOPEN, YES  },
105122840Smckusick 	 	{ "parameter",  SPARAM, YES  },
105222840Smckusick 	 	{ "pause",  SPAUSE  },
105322840Smckusick 	 	{ "print",  SPRINT  },
105422840Smckusick 	 	{ "program",  SPROGRAM, YES  },
105522840Smckusick 	 	{ "punch",  SPUNCH, YES  },
105622840Smckusick 	 	{ "read",  SREAD  },
105722840Smckusick 	 	{ "real",  SREAL  },
105822840Smckusick 	 	{ "return",  SRETURN  },
105922840Smckusick 	 	{ "rewind",  SREWIND  },
106022840Smckusick 	 	{ "save",  SSAVE, YES  },
106122840Smckusick 	 	{ "static",  SSTATIC, YES  },
106222840Smckusick 	 	{ "stop",  SSTOP  },
106322840Smckusick 	 	{ "subroutine",  SSUBROUTINE  },
106422840Smckusick 	 	{ "then",  STHEN, YES  },
106522840Smckusick 	 	{ "undefined", SUNDEFINED, YES  },
106622840Smckusick 	 	{ "write",  SWRITE  },
106722840Smckusick 			{ 0, 0 }
106822840Smckusick 	};
1069