renum.c
1 //! @file renum.c
2 //! @author J. Marcel van der Veer
3 //
4 //! @section Copyright
5 //
6 // This file is part of VIF - vintage FORTRAN compiler.
7 // Copyright 2020-2024 J. Marcel van der Veer <algol68g@xs4all.nl>.
8 //
9 //! @section License
10 //
11 // This program is free software; you can redistribute it and/or modify it
12 // under the terms of the GNU General Public License as published by the
13 // Free Software Foundation; either version 3 of the License, or
14 // (at your option) any later version.
15 //
16 // This program is distributed in the hope that it will be useful, but
17 // WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 // more details. You should have received a copy of the GNU General Public
20 // License along with this program. If not, see <http://www.gnu.org/licenses/>.
21
22 //! @section Synopsis
23 //!
24 //! Vintage Fortran statement renumbering tool.
25
26 // This code is based on a Pascal version that I wrote in the late 1980's.
27
28 #include <vif.h>
29
30 #define MODLEN 5000 // Max size of a subprogram
31
32 typedef RECORD DECK[MODLEN];
33
34 static RECORD name;
35
36 static int_4 routines, errors;
37 static int_4 old_label[MODLEN];
38
39 static int_4 P_eof (FILE * f)
40 {
41 if (feof (f)) {
42 return TRUE;
43 }
44 int_4 ch = getc (f);
45 if (ch == EOF) {
46 return TRUE;
47 }
48 ungetc (ch, f);
49 return FALSE;
50 }
51
52 static int_4 P_eoln (FILE *f)
53 {
54 int_4 ch = getc (f);
55 if (ch == EOF) {
56 return TRUE;
57 }
58 ungetc (ch, f);
59 return (ch == '\n');
60 }
61
62 static void write_sym (char *s)
63 {
64 for (int_4 i = 1; i < RECLN && s[i - 1] != ' '; i++) {
65 putchar (s[i - 1]);
66 }
67 putchar ('\n');
68 }
69
70 static void cram_symbol (char *b, char *s)
71 {
72 RECCLR (s);
73 for (int_4 i = 0, j = 0; i < RECLN; i++) {
74 if (b[i] != ' ') {
75 s[j++] = b[i];
76 }
77 }
78 }
79
80 static int_4 blank_card (char *a)
81 {
82 int_4 eq = TRUE;
83 for (int_4 i = 0; i < RECLN; i++) {
84 eq = (eq && a[i] == ' ');
85 }
86 return eq;
87 }
88
89 static void fill_buffer (FILE **f, RECORD *fsrc, int_4 *i)
90 {
91 int_4 j, kontinue = TRUE;
92 RECORD current_card, s;
93 RECCLR (s);
94 *i = 0;
95 while (kontinue) {
96 if (P_eof (*f) || *i >= MODLEN) {
97 continue;
98 }
99 memset (current_card, ' ', RECLN);
100 j = 0;
101 while (!P_eoln (*f) && j < RECLN) {
102 j++;
103 current_card[j - 1] = getc (*f);
104 if (current_card[j - 1] == '\n') {
105 current_card[j - 1] = ' ';
106 }
107 }
108 cram_symbol (current_card, s);
109 kontinue = !EQUAL (s, "end");
110 if (!blank_card (current_card)) {
111 (*i)++;
112 for (j = 0; j < RECLN; j++) {
113 fsrc[*i - 1][j] = current_card[j];
114 }
115 }
116 (void) fscanf (*f, "%*[^\n]");
117 getc (*f);
118 if (P_eof (*f)) {
119 kontinue = FALSE;
120 }
121 }
122 }
123
124 static void write_buffer (FILE **f, RECORD *fsrc, int_4 size)
125 {
126 int_4 i, j, last;
127
128 if (routines > 1) {
129 putc ('\n', *f);
130 }
131 for (i = 0; i < size; i++) {
132 last = strlen (fsrc[i]);
133 while (last > 0 && fsrc[i][last - 1] == ' ') {
134 last--;
135 }
136 for (j = 0; j < last; j++) {
137 putc (fsrc[i][j], *f);
138 }
139 putc ('\n', *f);
140 }
141 fflush (*f);
142 }
143
144 static int_4 isidchar (char c)
145 {
146 return (isalpha (c) || c == '$');
147 }
148
149 static int_4 isspecial (char c)
150 {
151 return (((!isidchar (c)) & (!isdigit (c))) && c != ' ');
152 }
153
154 static int_4 read_label (RECORD *b, int_4 flin)
155 {
156 int_4 signif, labval, column, digit;
157
158 if (IS_COMMENT (*(b[flin - 1]))) {
159 return 0;
160 } else {
161 signif = 1;
162 column = 5;
163 labval = 0;
164 while (column != 0) {
165 if (isdigit (b[flin - 1][column - 1])) {
166 digit = b[flin - 1][column - 1] - '0';
167 labval += signif * digit;
168 signif *= 10;
169 }
170 column--;
171 }
172 return labval;
173 }
174 }
175
176 static void write_label (RECORD *b, int_4 flin, int_4 lab)
177 {
178 int_4 i, digit;
179 int_4 column = 5, labval = lab;
180
181 do {
182 i = labval / 10;
183 digit = labval - i * 10;
184 labval = i;
185 b[flin - 1][column - 1] = (char) (digit + '0');
186 column--;
187 } while (labval != 0);
188 while (column != 0) {
189 b[flin - 1][column - 1] = ' ';
190 column--;
191 }
192 }
193
194 static void replace_label (RECORD *b, int_4 *flin, int_4 *first, int_4 *last, int_4 lab)
195 {
196 int_4 i;
197 int_4 j = 0;
198 int_4 k, digit, labval, FORLIM;
199
200 FORLIM = RECLN - *last;
201 for (i = 1; i <= FORLIM; i++) {
202 b[*flin - 1][*first + i - 1] = b[*flin - 1][*last + i - 2];
203 }
204 *last = *first + 1;
205 labval = lab;
206 do {
207 j++;
208 i = labval / 10;
209 digit = labval - i * 10;
210 labval = i;
211 b[*flin - 1][*first - 1] = (char) (digit + '0');
212 if (labval != 0) {
213 FORLIM = *first;
214 for (k = RECLN - 1; k >= FORLIM; k--) {
215 b[*flin - 1][k] = b[*flin - 1][k - 1];
216 }
217 (*last)++;
218 }
219 } while (labval != 0);
220 }
221
222 static void advance (RECORD *b, int_4 *eol, int_4 *cont, int_4 *flin, int_4 *column, int_4 *size)
223 {
224 if (*column != RECLN) {
225 (*column)++;
226 return;
227 }
228 do {
229 if (*flin == *size) {
230 *cont = FALSE;
231 } else {
232 (*flin)++;
233 }
234 } while (IS_COMMENT ((*b[*flin - 1])) && *cont);
235 if (!*cont) {
236 *column = 1;
237 *eol = TRUE;
238 return;
239 }
240 if (b[*flin - 1][5] != ' ') {
241 *column = 7;
242 return;
243 }
244 *column = 1;
245 *eol = TRUE;
246 *cont = FALSE;
247 }
248
249 static void scan_symbol (RECORD *b, char *s, int_4 *eol, int_4 *flin, int_4 *column, int_4 *first, int_4 *size)
250 {
251 int_4 i, cont = TRUE;
252 *eol = FALSE;
253 memset (s, ' ', RECLN);
254 while (b[*flin - 1][*column - 1] == ' ' && cont) {
255 advance (b, eol, &cont, flin, column, size);
256 }
257 if (cont && b[*flin - 1][*column - 1] == '\'') {
258 do {
259 advance (b, eol, &cont, flin, column, size);
260 while (cont && b[*flin - 1][*column - 1] != '\'') {
261 advance (b, eol, &cont, flin, column, size);
262 }
263 advance (b, eol, &cont, flin, column, size);
264 } while (cont && b[*flin - 1][*column - 1] == '\'');
265 }
266 *first = *column;
267 i = 0;
268 if (cont & isidchar (b[*flin - 1][*column - 1])) {
269 while ((isidchar (b[*flin - 1][*column - 1]) || isdigit (b[*flin - 1][*column - 1])) && cont) {
270 i++;
271 s[i - 1] = b[*flin - 1][*column - 1];
272 advance (b, eol, &cont, flin, column, size);
273 }
274 // Provision for 'endif' or 'end if' etcetera.
275 if (tolower (s[0]) == 'e' && tolower (s[1]) == 'n' && tolower (s[2]) == 'd') {
276 while (b[*flin - 1][*column - 1] == ' ' && cont) {
277 advance (b, eol, &cont, flin, column, size);
278 }
279 while (isidchar (b[*flin - 1][*column - 1]) && cont) {
280 i++;
281 s[i - 1] = b[*flin - 1][*column - 1];
282 advance (b, eol, &cont, flin, column, size);
283 }
284 }
285 s[i] = '\0';
286 cont = FALSE;
287 }
288 if (cont && isdigit (b[*flin - 1][*column - 1])) {
289 while (isdigit (b[*flin - 1][*column - 1]) && cont) {
290 i++;
291 s[i - 1] = b[*flin - 1][*column - 1];
292 advance (b, eol, &cont, flin, column, size);
293 }
294 s[i] = '\0';
295 cont = FALSE;
296 }
297 if (!(cont & isspecial (b[*flin - 1][*column - 1]))) {
298 return;
299 }
300 s[0] = b[*flin - 1][*column - 1];
301 advance (b, eol, &cont, flin, column, size);
302 s[1] = '\0';
303 cont = FALSE;
304 }
305
306 static int_4 new_label (char *c)
307 {
308 int_4 flin = 1;
309 int_4 labval = atoi (c);
310 while (old_label[flin - 1] != labval && flin < MODLEN) {
311 flin++;
312 }
313 if (flin < MODLEN) {
314 return flin;
315 }
316 message (NULL, ERR, "error", 0, "undefined label", c);
317 errors++;
318 return 0;
319 }
320
321 static void skip_to_comma (RECORD *b, char *s, int_4 *eol, int_4 *flin, int_4 *column, int_4 *first, int_4 *size)
322 {
323 int_4 nest = 0;
324 while (! (s[0] == ',' && nest == 0)) {
325 scan_symbol (b, s, eol, flin, column, first, size);
326 if (s[0] == '(') {
327 nest++;
328 } else if (s[0] == ')') {
329 if (nest == 0) {
330 return;
331 } else {
332 nest--;
333 }
334 }
335 }
336 }
337
338 static void relabel_io (RECORD *b, char *s, int_4 *eol, int_4 *flin, int_4 *column, int_4 *first, int_4 *size)
339 {
340 scan_symbol (b, s, eol, flin, column, first, size);
341 if (s[0] == '*') {
342 // print_4 *, ...
343 ;
344 } else if (isdigit (s[0])) {
345 // print_4 10, ...
346 replace_label (b, flin, first, column, new_label (s));
347 } else if (s[0] == '(') {
348 // print_4 (UNIT [,FMT=n],FILE=expr][,FORM=str][,ACTION=str][,DISP=str][,END=n][,ERR=n])
349 int_4 pos = 0;
350 do {
351 pos++;
352 scan_symbol (b, s, eol, flin, column, first, size);
353 if (s[0] == ',') {
354 ;
355 } else if (EQUAL (s, ")")) {
356 return;
357 } else if (EQUAL (s, "access")) {
358 skip_to_comma (b, s, eol, flin, column, first, size);
359 } else if (EQUAL (s, "action")) {
360 skip_to_comma (b, s, eol, flin, column, first, size);
361 } else if (EQUAL (s, "disp")) {
362 skip_to_comma (b, s, eol, flin, column, first, size);
363 } else if (EQUAL (s, "file")) {
364 skip_to_comma (b, s, eol, flin, column, first, size);
365 } else if (EQUAL (s, "form")) {
366 skip_to_comma (b, s, eol, flin, column, first, size);
367 } else if (EQUAL (s, "fmt") || EQUAL (s, "end") || EQUAL (s, "err")) {
368 scan_symbol (b, s, eol, flin, column, first, size);
369 scan_symbol (b, s, eol, flin, column, first, size);
370 replace_label (b, flin, first, column, new_label (s));
371 scan_symbol (b, s, eol, flin, column, first, size);
372 } else if (isdigit (s[0]) && pos == 2) {
373 replace_label (b, flin, first, column, new_label (s));
374 scan_symbol (b, s, eol, flin, column, first, size);
375 } else {
376 skip_to_comma (b, s, eol, flin, column, first, size);
377 }
378 } while (s[0] == ',');
379 }
380 }
381
382 static void relabel_goto (RECORD *b, char *s, int_4 *eol, int_4 *flin, int_4 *column, int_4 *first, int_4 *size)
383 {
384 do {
385 scan_symbol (b, s, eol, flin, column, first, size);
386 replace_label (b, flin, first, column, new_label (s));
387 scan_symbol (b, s, eol, flin, column, first, size);
388 } while (s[0] != ')');
389 }
390
391 static logical_4 relabel_statement (RECORD *b, char *s, int_4 *eol, int_4 *flin, int_4 *column, int_4 *first, int_4 *size)
392 {
393 if (EQUAL (s, "do")) {
394 scan_symbol (b, s, eol, flin, column, first, size);
395 if (isdigit (s[0])) {
396 replace_label (b, flin, first, column, new_label (s));
397 }
398 return TRUE;
399 }
400 if (EQUAL (s, "assign")) {
401 scan_symbol (b, s, eol, flin, column, first, size);
402 replace_label (b, flin, first, column, new_label (s));
403 return TRUE;
404 }
405 if (EQUAL (s, "read") || EQUAL (s, "accept")) {
406 relabel_io (b, s, eol, flin, column, first, size);
407 return TRUE;
408 }
409 if (EQUAL (s, "write") || EQUAL (s, "print") || EQUAL (s, "punch")) {
410 relabel_io (b, s, eol, flin, column, first, size);
411 return TRUE;
412 }
413 if (EQUAL (s, "goto") || EQUAL (s, "go")) {
414 if (EQUAL (s, "go")) {
415 scan_symbol (b, s, eol, flin, column, first, size);
416 }
417 scan_symbol (b, s, eol, flin, column, first, size);
418 if (s[0] == '(') {
419 relabel_goto (b, s, eol, flin, column, first, size);
420 } else if (isalpha (s[0])) {
421 scan_symbol (b, s, eol, flin, column, first, size);
422 if (s[0] == ',') {
423 scan_symbol (b, s, eol, flin, column, first, size);
424 }
425 relabel_goto (b, s, eol, flin, column, first, size);
426 } else {
427 replace_label (b, flin, first, column, new_label (s));
428 }
429 return TRUE;
430 }
431 if (EQUAL (s, "if")) {
432 scan_symbol (b, s, eol, flin, column, first, size);
433 int_4 nest = 1;
434 do {
435 scan_symbol (b, s, eol, flin, column, first, size);
436 if (s[0] == '(') {
437 nest++;
438 } else if (s[0] == ')') {
439 nest--;
440 }
441 } while (nest != 0);
442 scan_symbol (b, s, eol, flin, column, first, size);
443 if (isdigit (s[0])) {
444 replace_label (b, flin, first, column, new_label (s));
445 scan_symbol (b, s, eol, flin, column, first, size);
446 scan_symbol (b, s, eol, flin, column, first, size);
447 replace_label (b, flin, first, column, new_label (s));
448 scan_symbol (b, s, eol, flin, column, first, size);
449 if (EQUAL (s, ",")) {
450 scan_symbol (b, s, eol, flin, column, first, size);
451 replace_label (b, flin, first, column, new_label (s));
452 }
453 } else if (EQUAL (s, "goto") | EQUAL (s, "go")) {
454 relabel_statement (b, s, eol, flin, column, first, size);
455 } else if (EQUAL (s, "read") || EQUAL (s, "accept")) {
456 relabel_statement (b, s, eol, flin, column, first, size);
457 } else if (EQUAL (s, "write") || EQUAL (s, "print") || EQUAL (s, "punch")) {
458 relabel_statement (b, s, eol, flin, column, first, size);
459 } else if (EQUAL (s, "assign")) {
460 relabel_statement (b, s, eol, flin, column, first, size);
461 }
462 return TRUE;
463 }
464
465 return FALSE;
466 }
467
468 static void scan_statement (RECORD *b, int_4 size)
469 {
470 RECORD s;
471 int_4 eol, column, first;
472 int_4 flin = 1;
473 do {
474 column = 1;
475 do {
476 if (flin > size) {
477 eol = TRUE;
478 flin = size;
479 }
480 scan_symbol (b, s, &eol, &flin, &column, &first, &size);
481 if (relabel_statement (b, s, &eol, &flin, &column, &first, &size)) {
482 /* skip */;
483 }
484 } while (!eol);
485 } while (flin < size);
486 }
487
488 static void scan_name (RECORD *b, int_4 size, char *n)
489 {
490 RECORD s;
491 int_4 eol, column, first, i;
492
493 strcpy (n, "main");
494 int_4 flin = 1;
495 do {
496 column = 1;
497 if (IS_COMMENT (*(b[flin - 1]))) {
498 flin++;
499 } else {
500 do {
501 scan_symbol (b, s, &eol, &flin, &column, &first, &size);
502 if (EQUAL (s, "end")) {
503 eol = TRUE;
504 flin = size;
505 } else if (EQUAL (s, "program") || EQUAL (s, "subroutine") || EQUAL (s, "function")) {
506 scan_symbol (b, s, &eol, &flin, &column, &first, &size);
507 i = 1;
508 memset (n, ' ', RECLN);
509 while (i <= RECLN && s[i - 1] != '\0') {
510 n[i - 1] = s[i - 1];
511 i++;
512 }
513 }
514 } while (!eol);
515 }
516 } while (flin < size);
517 }
518
519 void relabel (char *fname)
520 {
521 RECORD gname;
522 FILE *infile, *outfile;
523 int_4 number;
524 static DECK fsrc;
525 RECCLR (gname);
526 if ((infile = fopen (fname, "r")) == NULL) {
527 FATAL (2401, "cannot open", fname);
528 };
529 strcpy (gname, fname);
530 for (int_4 k = (int_4) strlen (gname); k >= 0; k--) {
531 if (gname[k] == '.') {
532 gname[k] = '\0';
533 break;
534 }
535 }
536 //
537 strcat (gname, ".f~");
538 if ((outfile = fopen (gname, "w")) == NULL) {
539 FATAL (2402, "cannot open", gname);
540 };
541 //
542 routines = 0;
543 errors = 0;
544 do {
545 int_4 size;
546 fill_buffer (&infile, fsrc, &size);
547 if (size > 0) {
548 routines++;
549 for (int_4 i = 1; i <= size; i++) {
550 old_label[i - 1] = 0;
551 }
552 number = 0;
553 for (int_4 i = 1; i <= size; i++) {
554 int_4 labval = read_label (fsrc, i);
555 if (labval != 0) {
556 number++;
557 write_label (fsrc, i, number);
558 old_label[number - 1] = labval;
559 }
560 }
561 scan_name (fsrc, size, name);
562 scan_statement (fsrc, size);
563 write_buffer (&outfile, fsrc, size);
564 printf ("** ");
565 for (int_4 i = 1; i <= 10; i++) {
566 putchar (name[i - 1]);
567 }
568 printf (" ** end of renumber %d\n", routines);
569 }
570 } while (!P_eof (infile));
571 fclose (infile);
572 fclose (outfile);
573 return;
574 }
© 2002-2024 J.M. van der Veer (jmvdveer@xs4all.nl)
|