home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************
- Copyright 1990 by AT&T Bell Laboratories and Bellcore.
-
- Permission to use, copy, modify, and distribute this software
- and its documentation for any purpose and without fee is hereby
- granted, provided that the above copyright notice appear in all
- copies and that both that the copyright notice and this
- permission notice and warranty disclaimer appear in supporting
- documentation, and that the names of AT&T Bell Laboratories or
- Bellcore or any of their entities not be used in advertising or
- publicity pertaining to distribution of the software without
- specific, written prior permission.
-
- AT&T and Bellcore disclaim all warranties with regard to this
- software, including all implied warranties of merchantability
- and fitness. In no event shall AT&T or Bellcore be liable for
- any special, indirect or consequential damages or any damages
- whatsoever resulting from loss of use, data or profits, whether
- in an action of contract, negligence or other tortious action,
- arising out of or in connection with the use or performance of
- this software.
- ****************************************************************/
-
- #include "defs.h"
- #include "tokdefs.h"
- #include "p1defs.h"
-
- #define BLANK ' '
- #define MYQUOTE (2)
- #define SEOF 0
-
- /* card types */
-
- #define STEOF 1
- #define STINITIAL 2
- #define STCONTINUE 3
-
- /* lex states */
-
- #define NEWSTMT 1
- #define FIRSTTOKEN 2
- #define OTHERTOKEN 3
- #define RETEOS 4
-
-
- LOCAL int stkey; /* Type of the current statement (DO, END, IF, etc) */
- extern char token[]; /* holds the actual token text */
- static int needwkey;
- ftnint yystno;
- flag intonly;
- extern int new_dcl;
- LOCAL long int stno;
- LOCAL long int nxtstno; /* Statement label */
- LOCAL int parlev; /* Parentheses level */
- LOCAL int parseen;
- LOCAL int expcom;
- LOCAL int expeql;
- LOCAL char *nextch;
- LOCAL char *lastch;
- LOCAL char *nextcd = NULL;
- LOCAL char *endcd;
- LOCAL long prevlin;
- LOCAL long thislin;
- LOCAL int code; /* Card type; INITIAL, CONTINUE or EOF */
- LOCAL int lexstate = NEWSTMT;
- LOCAL char sbuf[1390]; /* Main buffer for Fortran source input. The number
- comes from lines of at most 66 characters, with at
- most 20 continuation cards (or something); this is
- part of the defn of the standard */
- LOCAL char *send = sbuf+20*66;
- LOCAL int nincl = 0; /* Current number of include files */
- LOCAL long firstline;
- LOCAL char *laststb, *stb0;
- extern int addftnsrc;
- #define CONTMAX 100 /* max continuation lines for ! processing */
- char *linestart[CONTMAX];
- LOCAL int ncont;
- LOCAL char comstart[Table_size];
- #define USC (unsigned char *)
-
- static char anum_buf[Table_size];
- #define isalnum_(x) anum_buf[x]
- #define isalpha_(x) (anum_buf[x] == 1)
-
- #define COMMENT_BUF_STORE 4088
-
- typedef struct comment_buf {
- struct comment_buf *next;
- char *last;
- char buf[COMMENT_BUF_STORE];
- } comment_buf;
- static comment_buf *cbfirst, *cbcur;
- static char *cbinit, *cbnext, *cblast;
- static void flush_comments();
- extern flag use_bs;
-
-
- /* Comment buffering data
-
- Comments are kept in a list until the statement before them has
- been parsed. This list is implemented with the above comment_buf
- structure and the pointers cbnext and cblast.
-
- The comments are stored with terminating NULL, and no other
- intervening space. The last few bytes of each block are likely to
- remain unused.
- */
-
- /* struct Inclfile holds the state information for each include file */
- struct Inclfile
- {
- struct Inclfile *inclnext;
- FILEP inclfp;
- char *inclname;
- int incllno;
- char *incllinp;
- int incllen;
- int inclcode;
- ftnint inclstno;
- };
-
- LOCAL struct Inclfile *inclp = NULL;
- struct Keylist {
- char *keyname;
- int keyval;
- char notinf66;
- };
- struct Punctlist {
- char punchar;
- int punval;
- };
- struct Fmtlist {
- char fmtchar;
- int fmtval;
- };
- struct Dotlist {
- char *dotname;
- int dotval;
- };
- LOCAL struct Keylist *keystart[26], *keyend[26];
-
- /* KEYWORD AND SPECIAL CHARACTER TABLES
- */
-
- static struct Punctlist puncts[ ] =
- {
- '(', SLPAR,
- ')', SRPAR,
- '=', SEQUALS,
- ',', SCOMMA,
- '+', SPLUS,
- '-', SMINUS,
- '*', SSTAR,
- '/', SSLASH,
- '$', SCURRENCY,
- ':', SCOLON,
- '<', SLT,
- '>', SGT,
- 0, 0 };
-
- LOCAL struct Dotlist dots[ ] =
- {
- "and.", SAND,
- "or.", SOR,
- "not.", SNOT,
- "true.", STRUE,
- "false.", SFALSE,
- "eq.", SEQ,
- "ne.", SNE,
- "lt.", SLT,
- "le.", SLE,
- "gt.", SGT,
- "ge.", SGE,
- "neqv.", SNEQV,
- "eqv.", SEQV,
- 0, 0 };
-
- LOCAL struct Keylist keys[ ] =
- {
- { "assign", SASSIGN },
- { "automatic", SAUTOMATIC, YES },
- { "backspace", SBACKSPACE },
- { "blockdata", SBLOCK },
- { "call", SCALL },
- { "character", SCHARACTER, YES },
- { "close", SCLOSE, YES },
- { "common", SCOMMON },
- { "complex", SCOMPLEX },
- { "continue", SCONTINUE },
- { "data", SDATA },
- { "dimension", SDIMENSION },
- { "doubleprecision", SDOUBLE },
- { "doublecomplex", SDCOMPLEX, YES },
- { "elseif", SELSEIF, YES },
- { "else", SELSE, YES },
- { "endfile", SENDFILE },
- { "endif", SENDIF, YES },
- { "enddo", SENDDO, YES },
- { "end", SEND },
- { "entry", SENTRY, YES },
- { "equivalence", SEQUIV },
- { "external", SEXTERNAL },
- { "format", SFORMAT },
- { "function", SFUNCTION },
- { "goto", SGOTO },
- { "implicit", SIMPLICIT, YES },
- { "include", SINCLUDE, YES },
- { "inquire", SINQUIRE, YES },
- { "intrinsic", SINTRINSIC, YES },
- { "integer", SINTEGER },
- { "logical", SLOGICAL },
- { "namelist", SNAMELIST, YES },
- { "none", SUNDEFINED, YES },
- { "open", SOPEN, YES },
- { "parameter", SPARAM, YES },
- { "pause", SPAUSE },
- { "print", SPRINT },
- { "program", SPROGRAM, YES },
- { "punch", SPUNCH, YES },
- { "read", SREAD },
- { "real", SREAL },
- { "return", SRETURN },
- { "rewind", SREWIND },
- { "save", SSAVE, YES },
- { "static", SSTATIC, YES },
- { "stop", SSTOP },
- { "subroutine", SSUBROUTINE },
- { "then", STHEN, YES },
- { "undefined", SUNDEFINED, YES },
- { "while", SWHILE, YES },
- { "write", SWRITE },
- { 0, 0 }
- };
-
- LOCAL void analyz(), crunch(), store_comment();
- LOCAL int getcd(), getcds(), getkwd(), gettok();
- LOCAL char *stbuf[3];
-
- inilex(name)
- char *name;
- {
- stbuf[0] = Alloc(3*P1_STMTBUFSIZE);
- stbuf[1] = stbuf[0] + P1_STMTBUFSIZE;
- stbuf[2] = stbuf[1] + P1_STMTBUFSIZE;
- nincl = 0;
- inclp = NULL;
- doinclude(name);
- lexstate = NEWSTMT;
- return(NO);
- }
-
-
-
- /* throw away the rest of the current line */
- flline()
- {
- lexstate = RETEOS;
- }
-
-
-
- char *lexline(n)
- int *n;
- {
- *n = (lastch - nextch) + 1;
- return(nextch);
- }
-
-
-
-
-
- doinclude(name)
- char *name;
- {
- FILEP fp;
- struct Inclfile *t;
-
- if(inclp)
- {
- inclp->incllno = thislin;
- inclp->inclcode = code;
- inclp->inclstno = nxtstno;
- if(nextcd)
- inclp->incllinp = copyn(inclp->incllen = endcd-nextcd , nextcd);
- else
- inclp->incllinp = 0;
- }
- nextcd = NULL;
-
- if(++nincl >= MAXINCLUDES)
- Fatal("includes nested too deep");
- if(name[0] == '\0')
- fp = stdin;
- else
- fp = fopen(name, textread);
- if (fp)
- {
- t = inclp;
- inclp = ALLOC(Inclfile);
- inclp->inclnext = t;
- prevlin = thislin = 0;
- infname = inclp->inclname = name;
- infile = inclp->inclfp = fp;
- }
- else
- {
- fprintf(diagfile, "Cannot open file %s\n", name);
- done(1);
- }
- }
-
-
-
-
- LOCAL popinclude()
- {
- struct Inclfile *t;
- register char *p;
- register int k;
-
- if(infile != stdin)
- clf(&infile, infname, 1); /* Close the input file */
- free(infname);
-
- --nincl;
- t = inclp->inclnext;
- free( (charptr) inclp);
- inclp = t;
- if(inclp == NULL) {
- infname = 0;
- return(NO);
- }
-
- infile = inclp->inclfp;
- infname = inclp->inclname;
- prevlin = thislin = inclp->incllno;
- code = inclp->inclcode;
- stno = nxtstno = inclp->inclstno;
- if(inclp->incllinp)
- {
- endcd = nextcd = sbuf;
- k = inclp->incllen;
- p = inclp->incllinp;
- while(--k >= 0)
- *endcd++ = *p++;
- free( (charptr) (inclp->incllinp) );
- }
- else
- nextcd = NULL;
- return(YES);
- }
-
- static void
- putlineno()
- {
- static long lastline;
- static char *lastfile = "??", *lastfile0 = "?";
- static char fbuf[P1_FILENAME_MAX];
- extern int gflag;
- register char *s0, *s1;
-
- if (gflag) {
- if (lastline) {
- if (lastfile != lastfile0) {
- p1puts(P1_FILENAME, fbuf);
- lastfile0 = lastfile;
- }
- p1_line_number(lastline);
- }
- lastline = firstline;
- if (lastfile != infname)
- if (lastfile = infname) {
- strncpy(fbuf, lastfile, sizeof(fbuf));
- fbuf[sizeof(fbuf)-1] = 0;
- }
- else
- fbuf[0] = 0;
- }
- if (addftnsrc) {
- if (laststb && *laststb) {
- for(s1 = laststb; *s1; s1++) {
- for(s0 = s1; *s1 != '\n'; s1++)
- if (*s1 == '*' && s1[1] == '/')
- *s1 = '+';
- *s1 = 0;
- p1puts(P1_FORTRAN, s0);
- }
- *laststb = 0; /* prevent trouble after EOF */
- }
- laststb = stb0;
- }
- }
-
-
- yylex()
- {
- static int tokno;
- int retval;
-
- switch(lexstate)
- {
- case NEWSTMT : /* need a new statement */
- retval = getcds();
- putlineno();
- if(retval == STEOF) {
- retval = SEOF;
- break;
- } /* if getcds() == STEOF */
- crunch();
- tokno = 0;
- lexstate = FIRSTTOKEN;
- yystno = stno;
- stno = nxtstno;
- toklen = 0;
- retval = SLABEL;
- break;
-
- first:
- case FIRSTTOKEN : /* first step on a statement */
- analyz();
- lexstate = OTHERTOKEN;
- tokno = 1;
- retval = stkey;
- break;
-
- case OTHERTOKEN : /* return next token */
- if(nextch > lastch)
- goto reteos;
- ++tokno;
- if( (stkey==SLOGIF || stkey==SELSEIF) && parlev==0 && tokno>3)
- goto first;
-
- if(stkey==SASSIGN && tokno==3 && nextch<lastch &&
- nextch[0]=='t' && nextch[1]=='o')
- {
- nextch+=2;
- retval = STO;
- break;
- }
- retval = gettok();
- break;
-
- reteos:
- case RETEOS:
- lexstate = NEWSTMT;
- retval = SEOS;
- break;
- default:
- fatali("impossible lexstate %d", lexstate);
- break;
- }
-
- if (retval == SEOF)
- flush_comments ();
-
- return retval;
- }
-
- /* Get Cards.
-
- Returns STEOF or STINITIAL, never STCONTINUE. Any continuation cards get
- merged into one long card (hence the size of the buffer named sbuf) */
-
- LOCAL int
- getcds()
- {
- register char *p, *q;
-
- flush_comments ();
- top:
- if(nextcd == NULL)
- {
- code = getcd( nextcd = sbuf, 1 );
- stno = nxtstno;
- prevlin = thislin;
- }
- if(code == STEOF)
- if( popinclude() )
- goto top;
- else
- return(STEOF);
-
- if(code == STCONTINUE)
- {
- lineno = thislin;
- nextcd = NULL;
- goto top;
- }
-
- /* Get rid of unused space at the head of the buffer */
-
- if(nextcd > sbuf)
- {
- q = nextcd;
- p = sbuf;
- while(q < endcd)
- *p++ = *q++;
- endcd = p;
- }
-
- /* Be aware that the input (i.e. the string at the address nextcd) is NOT
- NULL-terminated */
-
- /* This loop merges all continuations into one long statement, AND puts the next
- card to be read at the end of the buffer (i.e. it stores the look-ahead card
- when there's room) */
-
- ncont = 0;
- do {
- nextcd = endcd;
- if (ncont < CONTMAX)
- linestart[ncont++] = nextcd;
- }
- while(nextcd+66<=send && (code = getcd(nextcd,0))==STCONTINUE);
- nextch = sbuf;
- lastch = nextcd - 1;
-
- /* Handle buffer overflow by zeroing the 'next' pointer (nextcd) so that
- the top of this function will initialize it next time it is called */
-
- if(nextcd >= send)
- nextcd = NULL;
- lineno = prevlin;
- prevlin = thislin;
- return(STINITIAL);
- }
-
- static void
- bang(a,b,c,d,e) /* save ! comments */
- char *a, *b, *c;
- register char *d, *e;
- {
- char buf[COMMENT_BUFFER_SIZE + 1];
- register char *p, *pe;
-
- p = buf;
- pe = buf + COMMENT_BUFFER_SIZE;
- *pe = 0;
- while(a < b)
- if (!(*p++ = *a++))
- p[-1] = 0;
- if (b < c)
- *p++ = '\t';
- while(d < e) {
- if (!(*p++ = *d++))
- p[-1] = ' ';
- if (p == pe) {
- store_comment(buf);
- p = buf;
- }
- }
- if (p > buf) {
- while(--p >= buf && *p == ' ');
- p[1] = 0;
- store_comment(buf);
- }
- }
-
-
- /* getcd - Get next input card
-
- This function reads the next input card from global file pointer infile.
- It assumes that b points to currently empty storage somewhere in sbuf */
-
- LOCAL int
- getcd(b, nocont)
- register char *b;
- {
- register int c;
- register char *p, *bend;
- int speclin; /* Special line - true when the line is allowed
- to have more than 66 characters (e.g. the
- "&" shorthand for continuation, use of a "\t"
- to skip part of the label columns) */
- static char a[6]; /* Statement label buffer */
- static char *aend = a+6;
- static char *stb, *stbend;
- static int nst;
- char *atend, *endcd0;
- int amp;
- char storage[COMMENT_BUFFER_SIZE + 1];
- char *pointer;
-
- top:
- endcd = b;
- bend = b+66;
- amp = speclin = NO;
- atend = aend;
-
- /* Handle the continuation shorthand of "&" in the first column, which stands
- for " x" */
-
- if( (c = getc(infile)) == '&')
- {
- a[0] = c;
- a[1] = 0;
- a[5] = 'x';
- amp = speclin = YES;
- bend = send;
- p = aend;
- }
-
- /* Handle the Comment cards (a 'C', 'c', '*', or '!' in the first column). */
-
- else if(comstart[c & 0xfff])
- {
- if (feof (infile))
- return STEOF;
-
- storage[COMMENT_BUFFER_SIZE] = c = '\0';
- pointer = storage;
- while( !feof (infile) && (*pointer++ = c = getc(infile)) != '\n') {
-
- /* Handle obscure end of file conditions on many machines */
-
- if (feof (infile) && (c == '\377' || c == EOF)) {
- pointer--;
- break;
- } /* if (feof (infile)) */
-
- if (c == '\0')
- *(pointer - 1) = ' ';
-
- if (pointer == &storage[COMMENT_BUFFER_SIZE]) {
- store_comment (storage);
- pointer = storage;
- } /* if (pointer == BUFFER_SIZE) */
- } /* while */
-
- if (pointer > storage) {
- if (c == '\n')
-
- /* Get rid of the newline */
-
- pointer[-1] = 0;
- else
- *pointer = 0;
-
- store_comment (storage);
- } /* if */
-
- if (feof (infile))
- if (c != '\n') /* To allow the line index to
- increment correctly */
- return STEOF;
-
- ++thislin;
- goto top;
- }
-
- else if(c != EOF)
- {
-
- /* Load buffer a with the statement label */
-
- /* a tab in columns 1-6 skips to column 7 */
- ungetc(c, infile);
- for(p=a; p<aend && (c=getc(infile)) != '\n' && c!=EOF; )
- if(c == '\t')
-
- /* The tab character translates into blank characters in the statement label */
-
- {
- atend = p;
- while(p < aend)
- *p++ = BLANK;
- speclin = YES;
- bend = send;
- }
- else
- *p++ = c;
- }
-
- /* By now we've read either a continuation character or the statement label
- field */
-
- if(c == EOF)
- return(STEOF);
-
- /* The next 'if' block handles lines that have fewer than 7 characters */
-
- if(c == '\n')
- {
- while(p < aend)
- *p++ = BLANK;
-
- /* Blank out the buffer on lines which are not longer than 66 characters */
-
- endcd0 = endcd;
- if( ! speclin )
- while(endcd < bend)
- *endcd++ = BLANK;
- }
- else { /* read body of line */
- while( endcd<bend && (c=getc(infile)) != '\n' && c!=EOF )
- *endcd++ = c;
- if(c == EOF)
- return(STEOF);
-
- /* Drop any extra characters on the input card; this usually means those after
- column 72 */
-
- if(c != '\n')
- {
- while( (c=getc(infile)) != '\n')
- if(c == EOF)
- return(STEOF);
- }
-
- endcd0 = endcd;
- if( ! speclin )
- while(endcd < bend)
- *endcd++ = BLANK;
- }
-
- /* The flow of control usually gets to this line (unless an earlier RETURN has
- been taken) */
-
- ++thislin;
-
- /* Fortran 77 specifies that a 0 in column 6 */
- /* does not signify continuation */
-
- if( !isspace(a[5]) && a[5]!='0') {
- if (!amp)
- for(p = a; p < aend;)
- if (*p++ == '!' && p != aend)
- goto initcheck;
- if (addftnsrc && stb) {
- if (stbend > stb + 7) { /* otherwise forget col 1-6 */
- /* kludge around funny p1gets behavior */
- *stb++ = '$';
- if (amp)
- *stb++ = '&';
- else
- for(p = a; p < atend;)
- *stb++ = *p++;
- }
- if (endcd0 - b > stbend - stb) {
- if (stb > stbend)
- stb = stbend;
- endcd0 = b + (stbend - stb);
- }
- for(p = b; p < endcd0;)
- *stb++ = *p++;
- *stb++ = '\n';
- *stb = 0;
- }
- if (nocont) {
- lineno = thislin;
- errstr("illegal continuation card (starts \"%.6s\")",a);
- }
- else if (!amp && strncmp(a," ",5)) {
- lineno = thislin;
- errstr("labeled continuation line (starts \"%.6s\")",a);
- }
- return(STCONTINUE);
- }
- initcheck:
- for(p=a; p<atend; ++p)
- if( !isspace(*p) ) {
- if (*p++ != '!')
- goto initline;
- bang(p, atend, aend, b, endcd);
- goto top;
- }
- for(p = b ; p<endcd ; ++p)
- if( !isspace(*p) ) {
- if (*p++ != '!')
- goto initline;
- bang(a, a, a, p, endcd);
- goto top;
- }
-
- /* Skip over blank cards by reading the next one right away */
-
- goto top;
-
- initline:
- if (addftnsrc) {
- nst = (nst+1)%3;
- if (!laststb && stb0)
- laststb = stb0;
- stb0 = stb = stbuf[nst];
- *stb++ = '$'; /* kludge around funny p1gets behavior */
- stbend = stb + sizeof(stbuf[0])-2;
- for(p = a; p < atend;)
- *stb++ = *p++;
- if (atend < aend)
- *stb++ = '\t';
- for(p = b; p < endcd0;)
- *stb++ = *p++;
- *stb++ = '\n';
- *stb = 0;
- }
-
- /* Set nxtstno equal to the integer value of the statement label */
-
- nxtstno = 0;
- bend = a + 5;
- for(p = a ; p < bend ; ++p)
- if( !isspace(*p) )
- if(isdigit(*p))
- nxtstno = 10*nxtstno + (*p - '0');
- else if (*p == '!') {
- if (!addftnsrc)
- bang(p+1,atend,aend,b,endcd);
- endcd = b;
- break;
- }
- else {
- lineno = thislin;
- errstr(
- "nondigit in statement label field \"%.5s\"", a);
- nxtstno = 0;
- break;
- }
- firstline = thislin;
- return(STINITIAL);
- }
-
-
- /* crunch -- deletes all space characters, folds the backslash chars and
- Hollerith strings, quotes the Fortran strings */
-
- LOCAL void
- crunch()
- {
- register char *i, *j, *j0, *j1, *prvstr;
- int k, ten, nh, nh0, quote;
-
- /* i is the next input character to be looked at
- j is the next output character */
-
- new_dcl = needwkey = parlev = parseen = 0;
- expcom = 0; /* exposed ','s */
- expeql = 0; /* exposed equal signs */
- j = sbuf;
- prvstr = sbuf;
- k = 0;
- for(i=sbuf ; i<=lastch ; ++i)
- {
- if(isspace(*i) )
- continue;
- if (*i == '!') {
- while(i >= linestart[k])
- if (++k >= CONTMAX)
- Fatal("too many continuations\n");
- j0 = linestart[k];
- if (!addftnsrc)
- bang(sbuf,sbuf,sbuf,i+1,j0);
- i = j0-1;
- continue;
- }
-
- /* Keep everything in a quoted string */
-
- if(*i=='\'' || *i=='"')
- {
- int len = 0;
-
- quote = *i;
- *j = MYQUOTE; /* special marker */
- for(;;)
- {
- if(++i > lastch)
- {
- err("unbalanced quotes; closing quote supplied");
- if (j >= lastch)
- j = lastch - 1;
- break;
- }
- if(*i == quote)
- if(i<lastch && i[1]==quote) ++i;
- else break;
- else if(*i=='\\' && i<lastch && use_bs) {
- ++i;
- *i = escapes[*(unsigned char *)i];
- }
- if (len + 2 < MAXTOKENLEN)
- *++j = *i;
- else if (len + 2 == MAXTOKENLEN)
- erri
- ("String too long, truncating to %d chars", MAXTOKENLEN - 2);
- len++;
- } /* for (;;) */
-
- j[1] = MYQUOTE;
- j += 2;
- prvstr = j;
- }
- else if( (*i=='h' || *i=='H') && j>prvstr) /* test for Hollerith strings */
- {
- j0 = j - 1;
- if( ! isdigit(*j0)) goto copychar;
- nh = *j0 - '0';
- ten = 10;
- j1 = prvstr;
- if (j1+4 < j)
- j1 = j-4;
- for(;;) {
- if (j0-- <= j1)
- goto copychar;
- if( ! isdigit(*j0 ) ) break;
- nh += ten * (*j0-'0');
- ten*=10;
- }
- /* a hollerith must be preceded by a punctuation mark.
- '*' is possible only as repetition factor in a data statement
- not, in particular, in character*2h
- */
-
- if( !(*j0=='*'&&sbuf[0]=='d') && *j0!='/'
- && *j0!='(' && *j0!=',' && *j0!='=' && *j0!='.')
- goto copychar;
- nh0 = nh;
- if(i+nh > lastch || nh + 2 > MAXTOKENLEN)
- {
- erri("%dH too big", nh);
- nh = lastch - i;
- if (nh > MAXTOKENLEN - 2)
- nh = MAXTOKENLEN - 2;
- nh0 = -1;
- }
- j0[1] = MYQUOTE; /* special marker */
- j = j0 + 1;
- while(nh-- > 0)
- {
- if (++i > lastch) {
- hol_overflow:
- if (nh0 >= 0)
- erri("escapes make %dH too big",
- nh0);
- break;
- }
- if(*i == '\\' && use_bs) {
- if (++i > lastch)
- goto hol_overflow;
- *i = escapes[*(unsigned char *)i];
- }
- *++j = *i;
- }
- j[1] = MYQUOTE;
- j+=2;
- prvstr = j;
- }
- else {
- if(*i == '(') parseen = ++parlev;
- else if(*i == ')') --parlev;
- else if(parlev == 0)
- if(*i == '=') expeql = 1;
- else if(*i == ',') expcom = 1;
- copychar: /*not a string or space -- copy, shifting case if necessary */
- if(shiftcase && isupper(*i))
- *j++ = tolower(*i);
- else *j++ = *i;
- }
- }
- lastch = j - 1;
- nextch = sbuf;
- }
-
- LOCAL void
- analyz()
- {
- register char *i;
-
- if(parlev != 0)
- {
- err("unbalanced parentheses, statement skipped");
- stkey = SUNKNOWN;
- lastch = sbuf - 1; /* prevent double error msg */
- return;
- }
- if(nextch+2<=lastch && nextch[0]=='i' && nextch[1]=='f' && nextch[2]=='(')
- {
- /* assignment or if statement -- look at character after balancing paren */
- parlev = 1;
- for(i=nextch+3 ; i<=lastch; ++i)
- if(*i == (MYQUOTE))
- {
- while(*++i != MYQUOTE)
- ;
- }
- else if(*i == '(')
- ++parlev;
- else if(*i == ')')
- {
- if(--parlev == 0)
- break;
- }
- if(i >= lastch)
- stkey = SLOGIF;
- else if(i[1] == '=')
- stkey = SLET;
- else if( isdigit(i[1]) )
- stkey = SARITHIF;
- else stkey = SLOGIF;
- if(stkey != SLET)
- nextch += 2;
- }
- else if(expeql) /* may be an assignment */
- {
- if(expcom && nextch<lastch &&
- nextch[0]=='d' && nextch[1]=='o')
- {
- stkey = SDO;
- nextch += 2;
- }
- else stkey = SLET;
- }
- else if (parseen && nextch + 7 < lastch
- && nextch[2] != 'u' /* screen out "double..." early */
- && nextch[0] == 'd' && nextch[1] == 'o'
- && ((nextch[2] >= '0' && nextch[2] <= '9')
- || nextch[2] == ','
- || nextch[2] == 'w'))
- {
- stkey = SDO;
- nextch += 2;
- needwkey = 1;
- }
- /* otherwise search for keyword */
- else {
- stkey = getkwd();
- if(stkey==SGOTO && lastch>=nextch)
- if(nextch[0]=='(')
- stkey = SCOMPGOTO;
- else if(isalpha_(* USC nextch))
- stkey = SASGOTO;
- }
- parlev = 0;
- }
-
-
-
- LOCAL int
- getkwd()
- {
- register char *i, *j;
- register struct Keylist *pk, *pend;
- int k;
-
- if(! isalpha_(* USC nextch) )
- return(SUNKNOWN);
- k = letter(nextch[0]);
- if(pk = keystart[k])
- for(pend = keyend[k] ; pk<=pend ; ++pk )
- {
- i = pk->keyname;
- j = nextch;
- while(*++i==*++j && *i!='\0')
- ;
- if(*i=='\0' && j<=lastch+1)
- {
- nextch = j;
- if(no66flag && pk->notinf66)
- errstr("Not a Fortran 66 keyword: %s",
- pk->keyname);
- return(pk->keyval);
- }
- }
- return(SUNKNOWN);
- }
-
- initkey()
- {
- register struct Keylist *p;
- register int i,j;
- register char *s;
-
- for(i = 0 ; i<26 ; ++i)
- keystart[i] = NULL;
-
- for(p = keys ; p->keyname ; ++p) {
- j = letter(p->keyname[0]);
- if(keystart[j] == NULL)
- keystart[j] = p;
- keyend[j] = p;
- }
- comstart['c'] = comstart['C'] = comstart['*'] = comstart['!'] = 1;
- s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_";
- while(i = *s++)
- anum_buf[i] = 1;
- s = "0123456789";
- while(i = *s++)
- anum_buf[i] = 2;
- }
-
- LOCAL int
- hexcheck(key)
- int key;
- {
- register int radix;
- register char *p;
- char *kind;
-
- switch(key) {
- case 'z':
- case 'Z':
- case 'x':
- case 'X':
- radix = 16;
- key = SHEXCON;
- kind = "hexadecimal";
- break;
- case 'o':
- case 'O':
- radix = 8;
- key = SOCTCON;
- kind = "octal";
- break;
- case 'b':
- case 'B':
- radix = 2;
- key = SBITCON;
- kind = "binary";
- break;
- default:
- err("bad bit identifier");
- return(SNAME);
- }
- for(p = token; *p; p++)
- if (hextoi(*p) >= radix) {
- errstr("invalid %s character", kind);
- break;
- }
- return key;
- }
-
- /* gettok -- moves the right amount of text from nextch into the token
- buffer. token initially contains garbage (leftovers from the prev token) */
-
- LOCAL int
- gettok()
- {
- int havdot, havexp, havdbl;
- int radix, val;
- struct Punctlist *pp;
- struct Dotlist *pd;
- register int ch;
-
- char *i, *j, *n1, *p;
-
- ch = * USC nextch;
- if(ch == (MYQUOTE))
- {
- ++nextch;
- p = token;
- while(*nextch != MYQUOTE)
- *p++ = *nextch++;
- toklen = p - token;
- *p = 0;
- /* allow octal, binary, hex constants of the form 'abc'x (etc.) */
- if (++nextch <= lastch && isalpha_(val = * USC nextch)) {
- ++nextch;
- return hexcheck(val);
- }
- return (SHOLLERITH);
- }
-
- if(needkwd)
- {
- needkwd = 0;
- return( getkwd() );
- }
-
- for(pp=puncts; pp->punchar; ++pp)
- if(ch == pp->punchar) {
- val = pp->punval;
- if (++nextch <= lastch)
- switch(ch) {
- case '/':
- if (*nextch == '/') {
- nextch++;
- val = SCONCAT;
- }
- else if (new_dcl && parlev == 0)
- val = SSLASHD;
- return val;
- case '*':
- if (*nextch == '*') {
- nextch++;
- return SPOWER;
- }
- break;
- case '<':
- if (*nextch == '=') {
- nextch++;
- val = SLE;
- }
- if (*nextch == '>') {
- nextch++;
- val = SNE;
- }
- goto extchk;
- case '=':
- if (*nextch == '=') {
- nextch++;
- val = SEQ;
- goto extchk;
- }
- break;
- case '>':
- if (*nextch == '=') {
- nextch++;
- val = SGE;
- }
- extchk:
- NOEXT("Fortran 8x comparison operator");
- return val;
- }
- else if (ch == '/' && new_dcl && parlev == 0)
- return SSLASHD;
- switch(val) {
- case SLPAR:
- ++parlev;
- break;
- case SRPAR:
- --parlev;
- }
- return(val);
- }
- if(ch == '.')
- if(nextch >= lastch) goto badchar;
- else if(isdigit(nextch[1])) goto numconst;
- else {
- for(pd=dots ; (j=pd->dotname) ; ++pd)
- {
- for(i=nextch+1 ; i<=lastch ; ++i)
- if(*i != *j) break;
- else if(*i != '.') ++j;
- else {
- nextch = i+1;
- return(pd->dotval);
- }
- }
- goto badchar;
- }
- if( isalpha_(ch) )
- {
- p = token;
- *p++ = *nextch++;
- while(nextch<=lastch)
- if( isalnum_(* USC nextch) )
- *p++ = *nextch++;
- else break;
- toklen = p - token;
- *p = 0;
- if (needwkey) {
- needwkey = 0;
- if (toklen == 5
- && nextch <= lastch && *nextch == '(' /*)*/
- && !strcmp(token,"while"))
- return(SWHILE);
- }
- if(inioctl && nextch<=lastch && *nextch=='=')
- {
- ++nextch;
- return(SNAMEEQ);
- }
- if(toklen>8 && eqn(8,token,"function")
- && isalpha_(* USC (token+8)) &&
- nextch<lastch && nextch[0]=='(' &&
- (nextch[1]==')' || isalpha_(* USC (nextch+1))) )
- {
- nextch -= (toklen - 8);
- return(SFUNCTION);
- }
-
- if(toklen > 50)
- {
- char buff[100];
- sprintf(buff, toklen >= 60
- ? "name %.56s... too long, truncated to %.*s"
- : "name %s too long, truncated to %.*s",
- token, 50, token);
- err(buff);
- toklen = 50;
- token[50] = '\0';
- }
- if(toklen==1 && *nextch==MYQUOTE) {
- val = token[0];
- ++nextch;
- for(p = token ; *nextch!=MYQUOTE ; )
- *p++ = *nextch++;
- ++nextch;
- toklen = p - token;
- *p = 0;
- return hexcheck(val);
- }
- return(SNAME);
- }
-
- if (isdigit(ch)) {
-
- /* Check for NAG's special hex constant */
-
- if (nextch[1] == '#'
- || nextch[2] == '#' && isdigit(nextch[1])) {
-
- radix = atoi (nextch);
- if (*++nextch != '#')
- nextch++;
- if (radix != 2 && radix != 8 && radix != 16) {
- erri("invalid base %d for constant, defaulting to hex",
- radix);
- radix = 16;
- } /* if */
- if (++nextch > lastch)
- goto badchar;
- for (p = token; hextoi(*nextch) < radix;) {
- *p++ = *nextch++;
- if (nextch > lastch)
- break;
- }
- toklen = p - token;
- *p = 0;
- return (radix == 16) ? SHEXCON : ((radix == 8) ? SOCTCON :
- SBITCON);
- }
- }
- else
- goto badchar;
- numconst:
- havdot = NO;
- havexp = NO;
- havdbl = NO;
- for(n1 = nextch ; nextch<=lastch ; ++nextch)
- {
- if(*nextch == '.')
- if(havdot) break;
- else if(nextch+2<=lastch && isalpha_(* USC (nextch+1))
- && isalpha_(* USC (nextch+2)))
- break;
- else havdot = YES;
- else if( !intonly && (*nextch=='d' || *nextch=='e') )
- {
- p = nextch;
- havexp = YES;
- if(*nextch == 'd')
- havdbl = YES;
- if(nextch<lastch)
- if(nextch[1]=='+' || nextch[1]=='-')
- ++nextch;
- if( ! isdigit(*++nextch) )
- {
- nextch = p;
- havdbl = havexp = NO;
- break;
- }
- for(++nextch ;
- nextch<=lastch && isdigit(* USC nextch);
- ++nextch);
- break;
- }
- else if( ! isdigit(* USC nextch) )
- break;
- }
- p = token;
- i = n1;
- while(i < nextch)
- *p++ = *i++;
- toklen = p - token;
- *p = 0;
- if(havdbl) return(SDCON);
- if(havdot || havexp) return(SRCON);
- return(SICON);
- badchar:
- sbuf[0] = *nextch++;
- return(SUNKNOWN);
- }
-
- /* Comment buffering code */
-
- static void
- store_comment(str)
- char *str;
- {
- int len;
- comment_buf *ncb;
-
- if (nextcd == sbuf) {
- flush_comments();
- p1_comment(str);
- return;
- }
- len = strlen(str) + 1;
- if (cbnext + len > cblast) {
- if (!cbcur || !(ncb = cbcur->next)) {
- ncb = (comment_buf *) Alloc(sizeof(comment_buf));
- if (cbcur) {
- cbcur->last = cbnext;
- cbcur->next = ncb;
- }
- else {
- cbfirst = ncb;
- cbinit = ncb->buf;
- }
- ncb->next = 0;
- }
- cbcur = ncb;
- cbnext = ncb->buf;
- cblast = cbnext + COMMENT_BUF_STORE;
- }
- strcpy(cbnext, str);
- cbnext += len;
- }
-
- static void
- flush_comments()
- {
- register char *s, *s1;
- register comment_buf *cb;
- if (cbnext == cbinit)
- return;
- cbcur->last = cbnext;
- for(cb = cbfirst;; cb = cb->next) {
- for(s = cb->buf; s < cb->last; s = s1) {
- /* compute s1 = new s value first, since */
- /* p1_comment may insert nulls into s */
- s1 = s + strlen(s) + 1;
- p1_comment(s);
- }
- if (cb == cbcur)
- break;
- }
- cbcur = cbfirst;
- cbnext = cbinit;
- cblast = cbnext + COMMENT_BUF_STORE;
- }
-
- void
- unclassifiable()
- {
- register char *s, *se;
-
- s = sbuf;
- se = lastch;
- if (se < sbuf)
- return;
- lastch = s - 1;
- if (se - s > 10)
- se = s + 10;
- for(; s < se; s++)
- if (*s == MYQUOTE) {
- se = s;
- break;
- }
- *se = 0;
- errstr("unclassifiable statement (starts \"%s\")", sbuf);
- }
-