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