2
* ratfor - A ratfor pre-processor in C.
3
* Derived from a pre-processor distributed by the
4
* University of Arizona. Closely corresponds to the
5
* pre-processor described in the "SOFTWARE TOOLS" book.
9
* Not deived from AT&T code.
11
* This code is in the public domain. In other words, all rights
12
* are granted to all recipients, "public" at large.
14
* Modification history:
17
* - Ken Yap's mods for F77 output. Currently
18
* available thru #define F77.
19
* - Two minor bug-fixes for sane output.
21
* - Improve front-end with getopt().
22
* User may specify -l n for starting label.
23
* - Retrofit switch statement handling. This code
24
* is borrowed from the SWTOOLS Ratfor.
26
* 05-28-91 W. Bauske IBM
28
* - fixed line continuations
29
* - added -C option to leave comments in the source code
30
* - added % in column 1 to force copy to output
31
* - support both && and & for .and.
32
* - support both || and | for .or.
38
#if defined __stdc__ || defined __STDC__
60
LETE,LETL,LETS,LETE,EOS};
66
LETT,LETH,LETE,LETN,EOS};
69
LETE,LETN,LETD,LETI,LETF,EOS};
73
LETW, LETH, LETI, LETL, LETE, EOS};
78
LETB, LETR, LETE, LETA, LETK, EOS};
83
LETN,LETE, LETX, LETT, EOS};
88
LETF,LETO, LETR, EOS};
93
LETR, LETE, LETP, LETE, LETA, LETT, EOS};
98
LETU, LETN, LETT, LETI, LETL, EOS};
103
LETS, LETW, LETI, LETT, LETC, LETH, EOS};
108
LETC, LETA, LETS, LETE, EOS};
113
LETD, LETE, LETF, LETA, LETU, LETL, LETT, EOS};
118
LETR, LETE, LETT, LETU, LETR, LETN, EOS};
123
LETS, LETT, LETR, LETI, LETN, LETG, EOS};
130
/* constant strings */
132
char *errmsg = "error at line ";
134
char *ifnot = "if(.not.";
135
char *incl = "include";
136
char *fncn = "function";
137
char *def = "define";
138
char *bdef = "DEFINE";
139
char *contin = "continue";
140
char *rgoto = "goto ";
144
extern S_CHAR ngetch();
146
int startlab = 23000; /* default start label */
147
int leaveC = NO; /* Flag for handling comments */
150
* M A I N L I N E & I N I T
163
while ((c=our_getopt(argc, argv, "Chn:o:6:")) != EOF)
166
leaveC = YES; /* keep comments in src */
169
/* not written yet */
171
case 'l': /* user sets label */
172
startlab = atoi(optarg);
175
if ((freopen(optarg, "w", stdout)) == NULL)
176
error("can't write %s\n", optarg);
179
/* not written yet */
187
"usage: %s [-C][-hx][-l n][-o file][-6x] [file...]\n",progname);
192
* present version can only process one file, sadly.
194
if (optind77 >= argc)
196
else if ((infile[0] = fopen(argv[optind77], "r")) == NULL)
197
error("cannot read %s\n", argv[optind77]);
201
parse(); /* call parser.. */
213
outp = 0; /* output character pointer */
214
level = 0; /* file control */
215
linect[0] = 1; /* line count of first file */
218
bp = -1; /* pushback buffer pointer */
219
fordep = 0; /* for stack */
220
swtop = 0; /* switch stack index */
221
swlast = 1; /* switch stack index */
222
for( i = 0; i <= 126; i++)
224
install(def, deftyp); /* default definitions */
225
install(bdef, deftyp);
226
fcname[0] = EOS; /* current function name */
227
label = startlab; /* next generated label */
228
printf("C Output from Public domain Ratfor, version 1.0\n");
237
S_CHAR lexstr[MAXTOK];
238
int lab, labval[MAXSTACK], lextyp[MAXSTACK], sp, i, token;
242
for (token = lex(lexstr); token != EOF; token = lex(lexstr)) {
245
else if (token == LEXDO)
247
else if (token == LEXWHILE)
249
else if (token == LEXFOR)
251
else if (token == LEXREPEAT)
253
else if (token == LEXSWITCH)
255
else if (token == LEXCASE || token == LEXDEFAULT) {
256
for (i = sp; i >= 0; i--)
257
if (lextyp[i] == LEXSWITCH)
260
synerr("illegal case of default.");
262
cascod(labval[i], token);
264
else if (token == LEXDIGITS)
266
else if (token == LEXELSE) {
267
if (lextyp[sp] == LEXIF)
270
synerr("illegal else.");
272
if (token == LEXIF || token == LEXELSE || token == LEXWHILE
273
|| token == LEXFOR || token == LEXREPEAT
274
|| token == LEXDO || token == LEXDIGITS
275
|| token == LEXSWITCH || token == LBRACE) {
276
sp++; /* beginning of statement */
278
baderr("stack overflow in parser.");
279
lextyp[sp] = token; /* stack type and value */
282
else if (token != LEXCASE && token != LEXDEFAULT) {
284
* end of statement - prepare to unstack
286
if (token == RBRACE) {
287
if (lextyp[sp] == LBRACE)
289
else if (lextyp[sp] == LEXSWITCH) {
294
synerr("illegal right brace.");
296
else if (token == LEXOTHER)
298
else if (token == LEXBREAK || token == LEXNEXT)
299
brknxt(sp, lextyp, labval, token);
300
else if (token == LEXRETURN)
302
else if (token == LEXSTRING)
304
token = lex(lexstr); /* peek at next token */
306
unstak(&sp, lextyp, labval, token);
310
synerr("unexpected EOF.");
314
* L E X I C A L A N A L Y S E R
318
* alldig - return YES if str is all digits
330
for (i = 0; str[i] != EOS; i++)
331
if (type(str[i]) != DIGIT)
339
* balpar - copy balanced paren string
344
S_CHAR token[MAXTOK];
347
if (gnbtok(token, MAXTOK) != LPAREN) {
348
synerr("missing left paren.");
354
t = gettok(token, MAXTOK);
355
if (t==SEMICOL || t==LBRACE || t==RBRACE || t==EOF) {
359
if (t == NEWLINE) /* delete newlines */
361
else if (t == LPAREN)
363
else if (t == RPAREN)
365
/* else nothing special */
370
synerr("missing parenthesis in condition.");
374
* deftok - get token; process macro calls and invocations
378
deftok(token, toksiz, fd)
386
for (t=gtok(token, toksiz, fd); t!=EOF; t=gtok(token, toksiz, fd)) {
387
if (t != ALPHA) /* non-alpha */
389
if (look(token, defn) == NO) /* undefined */
391
if (defn[0] == DEFTYPE) { /* get definition */
392
getdef(token, toksiz, defn, MAXDEF, fd);
393
install(token, defn);
396
pbstr(defn); /* push replacement onto input */
398
if (t == ALPHA) /* convert to single case */
405
* eatup - process rest of statement; interpret continuations
411
S_CHAR ptoken[MAXTOK], token[MAXTOK];
416
t = gettok(token, MAXTOK);
417
if (t == SEMICOL || t == NEWLINE)
419
if (t == RBRACE || t == LBRACE) {
424
synerr("unexpected EOF.");
428
if (t == COMMA || t == PLUS
429
|| t == MINUS || t == STAR || t == LPAREN
430
|| t == AND || t == BAR || t == BANG
431
|| t == EQUALS || t == UNDERLINE ) {
432
while (gettok(ptoken, MAXTOK) == NEWLINE)
440
else if (t == RPAREN)
444
} while (nlpar >= 0);
447
synerr("unbalanced parentheses.");
451
* getdef (for no arguments) - get name and definition
454
getdef(token, toksiz, defn, defsiz, fd)
462
S_CHAR c, ptoken[MAXTOK];
466
* define(name,defn) or
470
if ((t = gtok(ptoken, MAXTOK, fd)) != LPAREN) {;
471
t = BLANK; /* define name defn */
475
if (gtok(token, toksiz, fd) != ALPHA)
476
baderr("non-alphanumeric name.");
478
c = (S_CHAR) gtok(ptoken, MAXTOK, fd);
479
if (t == BLANK) { /* define name defn */
485
baderr("definition too long.");
488
while (c != SHARP && c != NEWLINE && c != (S_CHAR)EOF && c != PERCENT);
489
if (c == SHARP || c == PERCENT)
492
else if (t == LPAREN) { /* define (name, defn) */
494
baderr("missing comma in define.");
495
/* else got (name, */
497
for (i = 0; nlpar >= 0; i++)
499
baderr("definition too long.");
500
else if (ngetch(&defn[i], fd) == (S_CHAR)EOF)
501
baderr("missing right paren.");
502
else if (defn[i] == LPAREN)
504
else if (defn[i] == RPAREN)
506
/* else normal character in defn[i] */
509
baderr("getdef is confused.");
514
* gettok - get token. handles file inclusion and line numbers
518
gettok(token, toksiz)
524
S_CHAR name[MAXNAME];
526
for ( ; level >= 0; level--) {
527
for (tok = deftok(token, toksiz, infile[level]); tok != EOF;
528
tok = deftok(token, toksiz, infile[level])) {
529
if (equal(token, fncn) == YES) {
530
skpblk(infile[level]);
531
t = deftok(fcname, MAXNAME, infile[level]);
534
synerr("missing function name.");
538
else if (equal(token, incl) == NO)
540
for (i = 0 ;; i = strlen((char *) (&name[0]))) {
541
t = deftok(&name[i], MAXNAME, infile[level]);
542
if (t == NEWLINE || t == SEMICOL) {
549
if (name[1] == SQUOTE) {
559
synerr("includes nested too deeply.");
563
infile[level+1] = fopen((char*)&name[2], "r");
565
infile[level+1] = fopen(name, "r");
568
if (infile[level+1] == NULL)
569
synerr("can't open include.");
572
if (fnamp + i <= MAXFNAMES) {
573
scopy(name, 0, fnames, fnamp);
574
fnamp = fnamp + i; /* push file name stack */
579
if (level > 0) { /* close include and pop file name stack */
580
fclose(infile[level]);
581
for (fnamp--; fnamp > 0; fnamp--)
582
if (fnames[fnamp-1] == EOS)
586
token[0] = EOF; /* in case called more than once */
593
* gnbtok - get nonblank token
597
gnbtok(token, toksiz)
603
skpblk(infile[level]);
604
tok = gettok(token, toksiz);
609
* gtok - get token for Ratfor
613
gtok(lexstr, toksiz, fd)
619
c = ngetch(&lexstr[0], fd);
620
if (c == BLANK || c == TAB) {
622
while (c == BLANK || c == TAB) /* compress many blanks to one */
626
outasis(fd); /* copy direct to output if % */
632
outcmnt(fd); /* copy comments to output */
636
while (ngetch(&c, fd) != NEWLINE) /* strip comments */
641
if(ngetch(&c, fd) == NEWLINE)
642
while(ngetch(&c, fd) == NEWLINE)
655
return((int)lexstr[0]);
659
if (tok == LETTER) { /* alpha */
660
for (i = 0; i < toksiz - 3; i++) {
661
tok = type(ngetch(&lexstr[i+1], fd));
662
/* Test for DOLLAR added by BM, 7-15-80 */
663
if (tok != LETTER && tok != DIGIT
664
&& tok != UNDERLINE && tok!=DOLLAR
671
else if (tok == DIGIT) { /* digits */
672
b = c - DIG0; /* in case alternate base number */
673
for (i = 0; i < toksiz - 3; i++) {
674
if (type(ngetch(&lexstr[i+1], fd)) != DIGIT)
676
b = 10*b + lexstr[i+1] - DIG0;
678
if (lexstr[i+1] == RADIX && b >= 2 && b <= 36) {
680
for (n = 0;; n = b*n + c - DIG0) {
681
c = ngetch(&lexstr[0], fd);
682
if (c >= LETA && c <= LETZ)
683
c = c - LETA + DIG9 + 1;
684
else if (c >= BIGA && c <= BIGZ)
685
c = c - BIGA + DIG9 + 1;
686
if (c < DIG0 || c >= DIG0 + b)
690
i = itoc(n, lexstr, toksiz);
697
else if (c == LBRACK) { /* allow [ for { */
701
else if (c == RBRACK) { /* allow ] for } */
706
else if (c == SQUOTE || c == DQUOTE) {
707
for (i = 1; ngetch(&lexstr[i], fd) != lexstr[0]; i++) {
708
if (lexstr[i] == UNDERLINE)
709
if (ngetch(&c, fd) == NEWLINE) {
710
while (c == NEWLINE || c == BLANK || c == TAB)
716
if (lexstr[i] == NEWLINE || i >= toksiz-1) {
717
synerr("missing quote.");
718
lexstr[i] = lexstr[0];
724
else if (c == PERCENT) {
725
outasis(fd); /* direct copy of protected */
728
else if (c == SHARP) {
730
outcmnt(fd); /* copy comments to output */
732
while (ngetch(&lexstr[0], fd) != NEWLINE) /* strip comments */
736
else if (c == GREATER || c == LESS || c == NOT
737
|| c == BANG || c == CARET || c == EQUALS
738
|| c == AND || c == OR)
739
i = relate(lexstr, fd);
741
synerr("token too long.");
743
if (lexstr[0] == NEWLINE)
744
linect[level] = linect[level] + 1;
746
#if defined(CRAY) || defined(GNU)
747
/* cray cannot compare char and ints, since EOF is an int we check with feof */
748
if (feof(fd)) tok = EOF;
755
* lex - return lexical type of token
765
for (tok = gnbtok(lexstr, MAXTOK);
766
tok == NEWLINE; tok = gnbtok(lexstr, MAXTOK))
768
if (tok == EOF || tok == SEMICOL || tok == LBRACE || tok == RBRACE)
772
else if (equal(lexstr, sif) == YES)
774
else if (equal(lexstr, selse) == YES)
776
else if (equal(lexstr, swhile) == YES)
778
else if (equal(lexstr, sdo) == YES)
780
else if (equal(lexstr, ssbreak) == YES)
782
else if (equal(lexstr, snext) == YES)
784
else if (equal(lexstr, sfor) == YES)
786
else if (equal(lexstr, srept) == YES)
788
else if (equal(lexstr, suntil) == YES)
790
else if (equal(lexstr, sswitch) == YES)
792
else if (equal(lexstr, scase) == YES)
794
else if (equal(lexstr, sdefault) == YES)
796
else if (equal(lexstr, sret) == YES)
798
else if (equal(lexstr, sstr) == YES)
806
* ngetch - get a (possibly pushed back) character
820
*c = (S_CHAR) getc(fd);
823
* check for a continuation '_\n'
824
* also removes UNDERLINES from
827
while ( *c == UNDERLINE)
834
*c = (S_CHAR) getc(fd);
851
*c = (S_CHAR) getc(fd);
859
* pbstr - push string back onto input
867
for (i = strlen((char *) (&in[0])) - 1; i >= 0; i--)
872
* putbak - push char back onto input
881
baderr("too many characters pushed back.");
887
* relate - convert relational shorthands into long form
896
if (ngetch(&token[1], fd) != EQUALS) {
904
token[5] = EOS; /* for .not. and .and. */
905
if (token[0] == GREATER)
907
else if (token[0] == LESS)
909
else if (token[0] == NOT || token[0] == BANG || token[0] == CARET) {
910
if (token[1] != EQUALS) {
917
else if (token[0] == EQUALS) {
918
if (token[1] != EQUALS) {
925
else if (token[0] == AND) { /* look for && or & */
926
if (ngetch(&token[1], fd) != AND)
933
else if (token[0] == OR) {
934
if (ngetch(&token[1], fd) != OR) /* look for || or | */
939
else /* can't happen */
942
return(strlen((char *) (&token[0]))-1);
946
* skpblk - skip blanks and tabs in file fd
954
for (c = ngetch(&c, fd); c == BLANK || c == TAB; c = ngetch(&c, fd))
961
* type - return LETTER, DIGIT or char; works with ascii alphabet
970
if (c >= DIG0 && c <= DIG9)
972
else if (c >= LETA && c <= LETZ)
974
else if (c >= BIGA && c <= BIGZ)
982
* C O D E G E N E R A T I O N
986
* brknxt - generate code for break n and next n; n = 1 is default
988
brknxt(sp, lextyp, labval, token)
995
S_CHAR t, ptoken[MAXTOK];
998
t = gnbtok(ptoken, MAXTOK);
999
if (alldig(ptoken) == YES) { /* have break n or next n */
1001
n = ctoi(ptoken, &i) - 1;
1003
else if (t != SEMICOL) /* default case */
1005
for (i = sp; i >= 0; i--)
1006
if (lextyp[i] == LEXWHILE || lextyp[i] == LEXDO
1007
|| lextyp[i] == LEXFOR || lextyp[i] == LEXREPEAT) {
1010
continue; /* seek proper level */
1012
else if (token == LEXBREAK)
1022
if (token == LEXBREAK)
1023
synerr("illegal break.");
1025
synerr("illegal next.");
1030
* docode - generate code for beginning of do
1046
* dostat - generate code for end of do statement
1057
* elseif - generate code for end of if before else
1075
* forcod - beginning of for statement
1081
S_CHAR t, token[MAXTOK];
1082
int i, j, nlpar,tlab;
1087
if (gnbtok(token, MAXTOK) != LPAREN) {
1088
synerr("missing left paren.");
1091
if (gnbtok(token, MAXTOK) != SEMICOL) { /* real init clause */
1097
if (gnbtok(token, MAXTOK) == SEMICOL) /* empty condition */
1099
else { /* non-empty condition */
1106
while (nlpar >= 0) {
1107
t = gettok(token, MAXTOK);
1112
else if (t == RPAREN)
1114
if (t == (S_CHAR)EOF) {
1118
if (t != NEWLINE && t != UNDERLINE)
1125
synerr("invalid for clause.");
1127
fordep++; /* stack reinit clause */
1129
for (i = 1; i < fordep; i++) /* find end *** should i = 1 ??? *** */
1130
j = j + strlen((char *) (&forstk[j])) + 1;
1131
forstk[j] = EOS; /* null, in case no reinit */
1133
t = gnbtok(token, MAXTOK);
1135
while (nlpar >= 0) {
1136
t = gettok(token, MAXTOK);
1139
else if (t == RPAREN)
1141
if (t == (S_CHAR)EOF) {
1145
if (nlpar >= 0 && t != NEWLINE && t != UNDERLINE) {
1146
if ((j + ((int) strlen((char *) (&token[0])))) >=
1148
baderr("for clause too long.");
1149
scopy(token, 0, forstk, j);
1150
j = j + strlen((char *) (&token[0]));
1153
tlab++; /* label for next's */
1158
* fors - process end of for statement
1169
for (i = 1; i < fordep; i++)
1170
j = j + strlen((char *) (&forstk[j])) + 1;
1171
if (((int) strlen((char *) (&forstk[j]))) > ((int) 0)) {
1182
* ifcode - generate initial code for if
1200
* ifend - generate code for end of if
1212
* ifgo - generate "if(.not.(...))goto lab"
1219
outtab(); /* get to column 7 */
1220
outstr(ifnot); /* " if(.not. " */
1221
balpar(); /* collect and output condition */
1222
outch(RPAREN); /* " ) " */
1223
outgo(lab); /* " goto lab " */
1228
* ifthen - generate "if((...))then"
1242
* labelc - output statement number
1249
xfer = NO; /* can't suppress goto's now */
1250
if (strlen((char *) (&lexstr[0])) == 5) /* warn about 23xxx labels */
1251
if (atoi((char*)lexstr) >= startlab)
1252
synerr("warning: possible label conflict.");
1258
* labgen - generate n consecutive labels, return first one
1273
* otherc - output ordinary Fortran statement
1287
* outch - put one char into output buffer
1295
if (outp >= 72) { /* continuation card */
1297
for (i = 0; i < 6; i++)
1307
* outcon - output "n continue"
1314
if (n <= 0 && outp == 0)
1315
return; /* don't need unlabeled continues */
1324
* outdon - finish off an output line
1330
outbuf[outp] = NEWLINE;
1331
outbuf[outp+1] = EOS;
1332
printf("%s", outbuf);
1337
* outcmnt - copy comment to output
1349
while((c=ngetch(&c,fd)) != NEWLINE) {
1353
printf("%s",comout);
1355
comout[comoutp]='C';
1361
comout[comoutp]=NEWLINE;
1362
comout[comoutp+1]=EOS;
1363
printf("%s",comout);
1367
* outasis - copy directly out
1374
while((c=ngetch(&c,fd)) != NEWLINE)
1380
* outgo - output "goto n"
1395
* outnum - output decimal number
1402
S_CHAR chars[MAXCHARS];
1409
chars[i] = (m % 10) + DIG0;
1412
while (m > 0 && i < MAXCHARS);
1415
for ( ; i >= 0; i--)
1422
* outstr - output string
1430
for (i=0; str[i] != EOS; i++)
1435
* outtab - get past column 6
1446
* repcod - generate code for beginning of repeat
1456
outcon(0); /* in case there was a label */
1459
*lab = ++tlab; /* label to go on next's */
1463
* retcod - generate code for return
1468
S_CHAR token[MAXTOK], t;
1470
t = gnbtok(token, MAXTOK);
1471
if (t != NEWLINE && t != SEMICOL && t != RBRACE) {
1479
else if (t == RBRACE)
1488
/* strdcl - generate code for string declaration */
1491
S_CHAR t, name[MAXNAME], init[MAXTOK];
1494
t = gnbtok(name, MAXNAME);
1496
synerr("missing string name.");
1497
if (gnbtok(init, MAXTOK) != LPAREN) { /* make size same as initial value */
1498
len = strlen((char *) (&init[0])) + 1;
1499
if (init[1] == SQUOTE || init[1] == DQUOTE)
1502
else { /* form is string name(size) init */
1503
t = gnbtok(init, MAXTOK);
1505
len = ctoi(init, &i);
1507
synerr("invalid string size.");
1508
if (gnbtok(init, MAXTOK) != RPAREN)
1509
synerr("missing right paren.");
1511
t = gnbtok(init, MAXTOK);
1524
len = strlen((char *)(&init[0])) + 1;
1525
if (init[0] == SQUOTE || init[0] == DQUOTE) {
1527
scopy(init, 1, init, 0);
1530
for (i = 1; i <= len; i++) { /* put out variable names */
1541
for (i = 0; init[i] != EOS; i++) { /* put out init */
1545
pbstr(eoss); /* push back EOS for subsequent substitution */
1550
* unstak - unstack at end of statement
1553
unstak(sp, lextyp, labval, token)
1562
for ( ; tp > 0; tp--) {
1563
if (lextyp[tp] == LBRACE)
1565
if (lextyp[tp] == LEXSWITCH)
1567
if (lextyp[tp] == LEXIF && token == LEXELSE)
1569
if (lextyp[tp] == LEXIF)
1575
else if (lextyp[tp] == LEXELSE) {
1581
outcon(labval[tp]+1);
1584
else if (lextyp[tp] == LEXDO)
1586
else if (lextyp[tp] == LEXWHILE)
1588
else if (lextyp[tp] == LEXFOR)
1590
else if (lextyp[tp] == LEXREPEAT)
1591
untils(labval[tp], token);
1597
* untils - generate code for until or end of repeat
1604
S_CHAR ptoken[MAXTOK];
1608
if (token == LEXUNTIL) {
1618
* whilec - generate code for beginning of while
1627
outcon(0); /* unlabeled continue, in case there was a label */
1639
* whiles - generate code for end of while
1654
* E R R O R M E S S A G E S
1658
* baderr - print error message, then die
1668
* error - print error message with one parameter, then die
1674
fprintf(stderr, msg,s);
1679
* synerr - report Ratfor syntax error
1684
S_CHAR lc[MAXCHARS];
1687
fprintf(stderr,errmsg);
1691
i = 0; /* for EOF errors */
1692
itoc(linect[i], lc, MAXCHARS);
1693
fprintf(stderr,(char*)lc);
1694
for (i = fnamp - 1; i > 1; i = i - 1)
1695
if (fnames[i-1] == EOS) { /* print file name */
1697
fprintf(stderr,(char*)&fnames[i]);
1700
fprintf(stderr,": \n %s\n",msg);
1705
* U T I L I T Y R O U T I N E S
1709
* ctoi - convert string at in[i] to int, increment i
1719
while (in[j] == BLANK || in[j] == TAB)
1721
for (k = 0; in[j] != EOS; j++) {
1722
if (in[j] < DIG0 || in[j] > DIG9)
1724
k = 10 * k + in[j] - DIG0;
1731
* fold - convert alphabetic token to single case
1740
/* WARNING - this routine depends heavily on the */
1741
/* fact that letters have been mapped into internal */
1742
/* right-adjusted ascii. god help you if you */
1743
/* have subverted this mechanism. */
1745
for (i = 0; token[i] != EOS; i++)
1746
if (token[i] >= BIGA && token[i] <= BIGZ)
1747
token[i] = token[i] - BIGA + LETA;
1751
* equal - compare str1 to str2; return YES if equal, NO if not
1761
for (i = 0; str1[i] == str2[i]; i++)
1768
* scopy - copy string at from[i] to to[j]
1771
scopy(from, i, to, j)
1780
for (k1 = i; from[k1] != EOS; k1++) {
1789
* look - look-up a definition
1797
extern struct hashlist *lookup();
1800
if ((p = lookup(name)) == NULL)
1802
(void) strcpy((char *) (&defn[0]),(char *) (&((p->def)[0])));
1807
* itoc - special version of itoa
1822
str[i++] = n % 10 + '0';
1824
while ((n /= 10) > 0 && i < size-2);
1825
if (sign < 0 && i < size-1)
1829
* reverse the string and plug it back in
1831
for (j = 0, k = strlen((char *) (&str[0])) - 1; j < k; j++, k--) {
1840
* cascod - generate code for case or default label
1847
int t, l, lb, ub, i, j, junk;
1848
S_CHAR scrtok[MAXTOK];
1851
synerr ("illegal case or default.");
1854
outgo(lab + 1); /* # terminate previous case */
1857
if (token == LEXCASE) { /* # case n[,n]... : ... */
1858
while (caslab (&lb, &t) != EOF) {
1861
junk = caslab (&ub, &t);
1863
synerr ("illegal range in case label.");
1866
if (swlast + 3 > MAXSWITCH)
1867
baderr ("switch table overflow.");
1868
for (i = swtop + 3; i < swlast; i = i + 3)
1869
if (lb <= swstak[i])
1871
else if (lb <= swstak[i+1])
1872
synerr ("duplicate case label.");
1873
if (i < swlast && ub >= swstak[i])
1874
synerr ("duplicate case label.");
1875
for (j = swlast; j > i; j--) /* # insert new entry */
1876
swstak[j+2] = swstak[j-1];
1880
swstak[swtop + 1] = swstak[swtop + 1] + 1;
1881
swlast = swlast + 3;
1884
else if (t != COMMA)
1885
synerr ("illegal case syntax.");
1888
else { /* # default : ... */
1889
t = gnbtok (scrtok, MAXTOK);
1890
if (swstak[swtop + 2] != 0)
1891
baderr ("multiple defaults in switch statement.");
1893
swstak[swtop + 2] = l;
1897
synerr ("unexpected EOF.");
1898
else if (t != COLON)
1899
baderr ("missing colon in case or default label.");
1906
* caslab - get one case label
1917
*t = gnbtok (tok, MAXTOK);
1918
while (*t == NEWLINE)
1919
*t = gnbtok (tok, MAXTOK);
1926
if (*t == MINUS || *t == PLUS)
1927
*t = gnbtok (tok, MAXTOK);
1929
synerr ("invalid case label.");
1934
*n = s * ctoi (tok, &i);
1936
*t = gnbtok (tok, MAXTOK);
1937
while (*t == NEWLINE)
1938
*t = gnbtok (tok, MAXTOK);
1942
* swcode - generate code for switch stmt.
1948
S_CHAR scrtok[MAXTOK];
1951
if (swlast + 3 > MAXSWITCH)
1952
baderr ("switch table overflow.");
1953
swstak[swlast] = swtop;
1954
swstak[swlast + 1] = 0;
1955
swstak[swlast + 2] = 0;
1957
swlast = swlast + 3;
1959
outtab(); /* # Innn=(e) */
1964
outgo(*lab); /* # goto L */
1966
while (gnbtok (scrtok, MAXTOK) == NEWLINE)
1968
if (scrtok[0] != LBRACE) {
1969
synerr ("missing left brace in switch statement.");
1975
* swend - finish off switch statement; generate dispatch code
1981
int lb, ub, n, i, j;
1983
static char *sif = "if (";
1984
static char *slt = ".lt.1.or.";
1985
static char *sgt = ".gt.";
1986
static char *sgoto = "goto (";
1987
static char *seq = ".eq.";
1988
static char *sge = ".ge.";
1989
static char *sle = ".le.";
1990
static char *sand = ".and.";
1992
lb = swstak[swtop + 3];
1993
ub = swstak[swlast - 2];
1994
n = swstak[swtop + 1];
1995
outgo(lab + 1); /* # terminate last case */
1996
if (swstak[swtop + 2] == 0)
1997
swstak[swtop + 2] = lab + 1; /* # default default label */
1999
outcon (lab); /* L continue */
2000
/* output branch table */
2002
if (n >= CUTOFF && ub - lb < DENSITY * n) {
2003
if (lb != 0) { * L Innn=Innn-lb *
2013
outtab(); * if (Innn.lt.1.or.Innn.gt.ub-lb+1)goto default *
2019
outnum (ub - lb + 1);
2021
outgo (swstak[swtop + 2]);
2023
outstr (sgoto); * goto ... *
2025
for (i = swtop + 3; i < swlast; i = i + 3) {
2026
* # fill in vacancies *
2027
for ( ; j < swstak[i]; j++) {
2028
outnum(swstak[swtop + 2]);
2031
for (j = swstak[i + 1] - swstak[i]; j >= 0; j--)
2032
outnum(swstak[i + 2]); * # fill in range *
2033
j = swstak[i + 1] + 1;
2042
else if (n > 0) { * # output linear search form *
2044
if (n > 0) { /* # output linear search form */
2045
for (i = swtop + 3; i < swlast; i = i + 3) {
2046
outtab(); /* # if (Innn */
2049
if (swstak[i] == swstak[i+1]) {
2050
outstr (seq); /* # .eq....*/
2054
outstr (sge); /* # .ge.lb.and.Innn.le.ub */
2059
outnum (swstak[i + 1]);
2061
outch (RPAREN); /* # ) goto ... */
2062
outgo (swstak[i + 2]);
2064
if (lab + 1 != swstak[swtop + 2])
2065
outgo (swstak[swtop + 2]);
2067
outcon (lab + 1); /* # L+1 continue */
2068
swlast = swtop; /* # pop switch stack */
2069
swtop = swstak[swtop];
2073
* swvar - output switch variable Innn, where nnn = lab