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