1 /* $Id: lex.c,v 1.12 2008/05/11 15:28:03 ragge Exp $ */
3 * Copyright(C) Caldera International Inc. 2001-2002. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * Redistributions of source code and documentation must retain the above
10 * copyright notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditionsand the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed or owned by Caldera
18 * Neither the name of Caldera International, Inc. nor the names of other
19 * contributors may be used to endorse or promote products derived from
20 * this software without specific prior written permission.
22 * USE OF THE SOFTWARE PROVIDED FOR UNDER THIS LICENSE BY CALDERA
23 * INTERNATIONAL, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL CALDERA INTERNATIONAL, INC. BE LIABLE
27 * FOR ANY DIRECT, INDIRECT INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OFLIABILITY, WHETHER IN CONTRACT,
31 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
32 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33 * POSSIBILITY OF SUCH DAMAGE.
60 LOCAL
long int nxtstno
;
66 LOCAL
char *nextcd
= NULL
;
71 LOCAL
int lexstate
= NEWSTMT
;
73 LOCAL
char *send
= s
+20*66;
78 struct inclfile
*inclnext
;
88 LOCAL
struct inclfile
*inclp
= NULL
;
89 struct keylist
{ char *keyname
; int keyval
; } ;
90 struct punctlist
{ char punchar
; int punval
; };
91 struct fmtlist
{ char fmtchar
; int fmtval
; };
92 struct dotlist
{ char *dotname
; int dotval
; };
93 LOCAL
struct dotlist dots
[];
94 LOCAL
struct keylist
*keystart
[26], *keyend
[26];
95 LOCAL
struct keylist keys
[];
97 LOCAL
int getcds(void);
98 LOCAL
void crunch(void);
99 LOCAL
void analyz(void);
100 LOCAL
int gettok(void);
101 LOCAL
int getcd(char *b
);
102 LOCAL
int getkwd(void);
103 LOCAL
int popinclude(void);
106 * called from main() to start parsing.
107 * name[0] may be \0 if stdin.
121 /* throw away the rest of the current line */
133 *n
= (lastch
- nextch
) + 1;
141 doinclude(char *name
)
147 inclp
->incllno
= thislin
;
148 inclp
->inclcode
= code
;
149 inclp
->inclstno
= nxtstno
;
152 copyn(inclp
->incllen
= endcd
-nextcd
, nextcd
);
158 if(++nincl
>= MAXINCLUDES
)
159 fatal("includes nested too deep");
163 fp
= fopen(name
, "r");
166 inclp
= ALLOC(inclfile
);
168 prevlin
= thislin
= 0;
169 infname
= inclp
->inclname
= name
;
170 infile
= inclp
->inclfp
= fp
;
172 fprintf(diagfile
, "Cannot open file %s", name
);
198 infile
= inclp
->inclfp
;
199 infname
= inclp
->inclname
;
200 prevlin
= thislin
= inclp
->incllno
;
201 code
= inclp
->inclcode
;
202 stno
= nxtstno
= inclp
->inclstno
;
203 if(inclp
->incllinp
) {
209 ckfree(inclp
->incllinp
);
224 case NEWSTMT
: /* need a new statement */
225 if(getcds() == STEOF
)
229 lexstate
= FIRSTTOKEN
;
236 case FIRSTTOKEN
: /* first step on a statement */
238 lexstate
= OTHERTOKEN
;
242 case OTHERTOKEN
: /* return next token */
246 if((stkey
==SLOGIF
|| stkey
==SELSEIF
) && parlev
==0 && tokno
>3) goto first
;
247 if(stkey
==SASSIGN
&& tokno
==3 && nextch
<lastch
&&
248 nextch
[0]=='t' && nextch
[1]=='o')
260 fatal1("impossible lexstate %d", lexstate
);
262 return 0; /* XXX gcc */
268 register char *p
, *q
;
273 code
= getcd( nextcd
= s
);
283 if(code
== STCONTINUE
)
286 err("illegal continuation card ignored");
300 nextcd
+66<=send
&& (code
= getcd(nextcd
))==STCONTINUE
;
317 register char *p
, *bend
;
320 static char *aend
= a
+6;
327 if( (c
= getc(infile
)) == '&')
334 else if(c
=='c' || c
=='C' || c
=='*')
336 while( (c
= getc(infile
)) != '\n')
345 /* a tab in columns 1-6 skips to column 7 */
347 for(p
=a
; p
<aend
&& (c
=getc(infile
)) != '\n' && c
!=EOF
; )
369 else { /* read body of line */
370 while( endcd
<bend
&& (c
=getc(infile
)) != '\n' && c
!=EOF
)
371 *endcd
++ = (c
== '\t' ? BLANK
: c
);
376 while( (c
=getc(infile
)) != '\n')
386 if(a
[5]!=BLANK
&& a
[5]!='0')
388 for(p
=a
; p
<aend
; ++p
)
389 if(*p
!= BLANK
) goto initline
;
390 for(p
= b
; p
<endcd
; ++p
)
391 if(*p
!= BLANK
) goto initline
;
396 for(p
= a
; p
<a
+5 ; ++p
)
399 nxtstno
= 10*nxtstno
+ (*p
- '0');
402 err("nondigit in statement number field");
413 register char *i
, *j
, *j0
, *j1
, *prvstr
;
416 /* i is the next input character to be looked at
417 j is the next output character */
419 expcom
= 0; /* exposed ','s */
420 expeql
= 0; /* exposed equal signs */
423 for(i
=s
; i
<=lastch
; ++i
)
425 if(*i
== BLANK
) continue;
426 if(*i
=='\'' || *i
=='"')
429 *j
= MYQUOTE
; /* special marker */
434 err("unbalanced quotes; closing quote supplied");
438 if(i
<lastch
&& i
[1]==quote
) ++i
;
440 else if(*i
=='\\' && i
<lastch
)
462 else if( (*i
=='h' || *i
=='H') && j
>prvstr
) /* test for Hollerith strings */
464 if( ! isdigit((int)j
[-1])) goto copychar
;
469 for(j0
=j
-2 ; j0
>j1
; -- j0
)
471 if( ! isdigit((int)*j0
) ) break;
472 nh
+= ten
* (*j0
-'0');
475 if(j0
<= j1
) goto copychar
;
476 /* a hollerith must be preceded by a punctuation mark.
477 '*' is possible only as repetition factor in a data statement
478 not, in particular, in character*2h
481 if( !(*j0
=='*'&&s
[0]=='d') && *j0
!='/' && *j0
!='(' &&
482 *j0
!=',' && *j0
!='=' && *j0
!='.')
486 err1("%dH too big", nh
);
489 j0
[1] = MYQUOTE
; /* special marker */
516 if(*i
== '(') ++parlev
;
517 else if(*i
== ')') --parlev
;
518 else if(parlev
== 0) {
519 if(*i
== '=') expeql
= 1;
520 else if(*i
== ',') expcom
= 1;
521 copychar
: ; /*not a string of BLANK -- copy, shifting case if necessary */
523 if(shiftcase
&& isupper((int)*i
))
524 *j
++ = tolower((int)*i
);
539 err("unbalanced parentheses, statement skipped");
543 if(nextch
+2<=lastch
&& nextch
[0]=='i' && nextch
[1]=='f' && nextch
[2]=='(')
545 /* assignment or if statement -- look at character after balancing paren */
547 for(i
=nextch
+3 ; i
<=lastch
; ++i
)
550 while(*++i
!= MYQUOTE
)
564 else if( isdigit((int)i
[1]) )
570 else if(expeql
) /* may be an assignment */
572 if(expcom
&& nextch
<lastch
&&
573 nextch
[0]=='d' && nextch
[1]=='o')
580 /* otherwise search for keyword */
583 if(stkey
==SGOTO
&& lastch
>=nextch
) {
586 else if(isalpha((int)nextch
[0]))
598 register char *i
, *j
;
599 register struct keylist
*pk
, *pend
;
602 if(! isalpha((int)nextch
[0]) )
605 if((pk
= keystart
[k
]))
606 for(pend
= keyend
[k
] ; pk
<=pend
; ++pk
)
610 while(*++i
==*++j
&& *i
!='\0')
625 register struct keylist
*p
;
628 for(i
= 0 ; i
<26 ; ++i
)
631 for(p
= keys
; p
->keyname
; ++p
)
633 j
= p
->keyname
[0] - 'a';
634 if(keystart
[j
] == NULL
)
643 int havdot
, havexp
, havdbl
;
645 extern struct punctlist puncts
[];
646 struct punctlist
*pp
;
648 extern struct fmtlist fmts
[];
652 char *i
, *j
, *n1
, *p
;
654 if(*nextch
== (MYQUOTE
))
658 while(*nextch
!= MYQUOTE
)
668 for(pf = fmts; pf->fmtchar; ++pf)
670 if(*nextch == pf->fmtchar)
673 if(pf->fmtval == SLPAR)
675 else if(pf->fmtval == SRPAR)
680 if( isdigit(*nextch) )
684 while(nextch<=lastch && isdigit(*nextch) )
688 if(nextch<=lastch && *nextch=='p')
695 if( isalpha(*nextch) )
699 while(nextch<=lastch &&
700 (*nextch=='.' || isdigit(*nextch) || isalpha(*nextch) ))
709 /* Not a format statement */
717 for(pp
=puncts
; pp
->punchar
; ++pp
)
718 if(*nextch
== pp
->punchar
)
720 if( (*nextch
=='*' || *nextch
=='/') &&
721 nextch
<lastch
&& nextch
[1]==nextch
[0])
725 else yylval
.num
= SCONCAT
;
728 else {yylval
.num
=pp
->punval
;
729 if(yylval
.num
==SLPAR
)
731 else if(yylval
.num
==SRPAR
)
738 if(nextch
>= lastch
) goto badchar
;
739 else if(isdigit((int)nextch
[1])) goto numconst
;
741 for(pd
=dots
; (j
=pd
->dotname
) ; ++pd
)
743 for(i
=nextch
+1 ; i
<=lastch
; ++i
)
745 else if(*i
!= '.') ++j
;
754 if( isalpha((int)*nextch
) )
758 while(nextch
<=lastch
)
759 if( isalpha((int)*nextch
) || isdigit((int)*nextch
) )
764 if(inioctl
&& nextch
<=lastch
&& *nextch
=='=')
769 if(toklen
>=8 && eqn(8, token
, "function") &&
770 nextch
<lastch
&& *nextch
=='(')
772 nextch
-= (toklen
- 8);
777 err2("name %s too long, truncated to %d", token
, VL
);
781 if(toklen
==1 && *nextch
==MYQUOTE
)
793 err("bad bit identifier");
797 for(p
= token
; *nextch
!=MYQUOTE
; )
798 if( hextoi(*p
++ = *nextch
++) >= radix
)
800 err("invalid binary character");
805 return( radix
==16 ? SHEXCON
: (radix
==8 ? SOCTCON
: SBITCON
) );
809 if( ! isdigit((int)*nextch
) ) goto badchar
;
814 for(n1
= nextch
; nextch
<=lastch
; ++nextch
)
818 else if(nextch
+2<=lastch
&& isalpha((int)nextch
[1])
819 && isalpha((int)nextch
[2]))
822 else if(*nextch
=='d' || *nextch
=='e')
829 if(nextch
[1]=='+' || nextch
[1]=='-')
831 if( ! isdigit((int)*++nextch
) )
834 havdbl
= havexp
= NO
;
838 nextch
<=lastch
&& isdigit((int)*nextch
);
842 else if( ! isdigit((int)*nextch
) )
851 if(havdbl
) return(SDCON
);
852 if(havdot
|| havexp
) return(SRCON
);
859 /* KEYWORD AND SPECIAL CHARACTER TABLES
862 struct punctlist puncts
[ ] =
877 LOCAL struct fmtlist fmts[ ] =
888 LOCAL
struct dotlist dots
[ ] =
894 { "false.", SFALSE
, },
905 LOCAL
struct keylist keys
[ ] =
907 { "assign", SASSIGN
, },
908 { "automatic", SAUTOMATIC
, },
909 { "backspace", SBACKSPACE
, },
910 { "blockdata", SBLOCK
, },
912 { "character", SCHARACTER
, },
913 { "close", SCLOSE
, },
914 { "common", SCOMMON
, },
915 { "complex", SCOMPLEX
, },
916 { "continue", SCONTINUE
, },
918 { "dimension", SDIMENSION
, },
919 { "doubleprecision", SDOUBLE
, },
920 { "doublecomplex", SDCOMPLEX
, },
921 { "elseif", SELSEIF
, },
923 { "endfile", SENDFILE
, },
924 { "endif", SENDIF
, },
926 { "entry", SENTRY
, },
927 { "equivalence", SEQUIV
, },
928 { "external", SEXTERNAL
, },
929 { "format", SFORMAT
, },
930 { "function", SFUNCTION
, },
932 { "implicit", SIMPLICIT
, },
933 { "include", SINCLUDE
, },
934 { "inquire", SINQUIRE
, },
935 { "intrinsic", SINTRINSIC
, },
936 { "integer", SINTEGER
, },
937 { "logical", SLOGICAL
, },
939 { "parameter", SPARAM
, },
940 { "pause", SPAUSE
, },
941 { "print", SPRINT
, },
942 { "program", SPROGRAM
, },
943 { "punch", SPUNCH
, },
946 { "return", SRETURN
, },
947 { "rewind", SREWIND
, },
949 { "static", SSTATIC
, },
951 { "subroutine", SSUBROUTINE
, },
953 { "undefined", SUNDEFINED
, },
954 { "write", SWRITE
, },