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