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