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