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