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