fpp.c
1 //! @file fpp.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-2025 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 //! Fortran preprocessor.
25
26 #include <vif.h>
27
28 void fpp (char *, char *, int_4 nest);
29
30 int_4 register_file(char *name)
31 {
32 for (int_4 k = 1; k <= nfiles; k++) {
33 if (strcmp (files[k].text, name) == 0) {
34 return k;
35 }
36 }
37 nfiles++;
38 if (nfiles >= MAX_SOURCE_FILES) {
39 FATAL (1701, "too many source files", NO_TEXT);
40 }
41 files[nfiles].num = nfiles;
42 files[nfiles].text = f_stralloc (name);
43 return nfiles;
44 }
45
46 void get_source (char *name, int_4 nest)
47 {
48 FILE *in;
49 char *ext;
50 int_4 lines = 1, nisn = 0, actfile, cntrls = 0;
51 if (nest > MAX_NEST) {
52 FATAL (1702, "include nesting too deep", name);
53 }
54 if (strlen (name) < 3) {
55 FATAL (1703, "source file name", name);
56 }
57 ext = &name[strlen (name) - 2];
58 if (EQUAL (ext, ".f") || EQUAL (ext, ".F")) {
59 ;// Ok
60 } else if (EQUAL (ext, ".ftn") || EQUAL (ext, ".FTN")) {
61 ;// Ok
62 } else if (EQUAL (ext, ".h") || EQUAL (ext, ".H")) {
63 ;// Ok
64 } else {
65 FATAL (1704, "source file format", name);
66 }
67 if ((in = fopen (name, "r")) == NO_FILE) {
68 FATAL (1705, "cannot read", name);
69 };
70 RECORD path;
71 _srecordf (path, "%s", dirname (name));
72 actfile = register_file(name);
73 while (!feof (in)) {
74 RECORD fetch;
75 RECCLR (fetch);
76 if (fgets (fetch, RECLN, in) != NO_TEXT) {
77 int_4 len = strlen (fetch);
78 if (len > 0) {
79 for (int k = 0; k < len; k++) {
80 if (fetch[k] == EOF || fetch[k] == '\0' || fetch[k] == '\n') {
81 ;
82 } else if (fetch[k] == '\r' && fetch[k + 1] == '\n') {
83 // Assume ms-dos that has \r\n line ends.
84 fetch[k] = '\n';
85 fetch[k + 1] = '\0';
86 len--;
87 } else {
88 if (!isprint (fetch[k])) {
89 cntrls++;
90 fetch[k] = '?';
91 }
92 }
93 }
94 if (fetch[0] == '#') {
95 int_4 savfile = actfile;
96 fpp (fetch, path, nest);
97 actfile = savfile;
98 lines++;
99 } else {
100 if (fetch[len - 1] == '\n') {
101 fetch[--len] = '\0';
102 }
103 if (nftnlines == MAX_FTN_LINES - 1) { // One less - always terminating NULL line.
104 MAX_FTN_LINES += INCREMENT;
105 source = (FTN_LINE *) f_realloc (source, MAX_FTN_LINES * sizeof (FTN_LINE));
106 memset (&source[nftnlines], 0, INCREMENT * sizeof (FTN_LINE));
107 }
108 source[nftnlines].file = &files[actfile];
109 source[nftnlines].num = lines;
110 source[nftnlines].len = len;
111 source[nftnlines].jcl = FALSE;
112 source[nftnlines].text = f_stralloc (fetch);
113 if (fetch[0] == '\0' || IS_COMMENT (fetch[0])) {
114 source[nftnlines].isn = 0;
115 } else if (nisn > 0 && fetch[5] != ' ') {
116 source[nftnlines].isn = nisn;
117 } else {
118 source[nftnlines].isn = ++nisn;
119 }
120 lines++;
121 nftnlines++;
122 }
123 }
124 }
125 }
126 files[nfiles].len = lines - 1;
127 fclose (in);
128 if (cntrls > 0) {
129 WARNING (1706, "source has unrecognized characters", NO_TEXT);
130 }
131 }
132
133 void fpp (char *cmd, char *path, int_4 nest)
134 {
135 if (cmd[0] == '#') {
136 cmd++;
137 }
138 while (cmd[0] == ' ') {
139 cmd++;
140 }
141 if (LEQUAL ("echo", cmd)) {
142 cmd = &cmd[strlen ("echo")];
143 while (cmd[0] == ' ') {
144 cmd++;
145 }
146 int_4 N = strlen (cmd);
147 if (N > 0 && cmd[N - 1] == '\n') {
148 cmd[N - 1] = '\0';
149 }
150 ECHO (1707, cmd, NO_TEXT);
151 } else if (LEQUAL ("pragma", cmd)) {
152 cmd = &cmd[strlen ("pragma")];
153 while (cmd[0] == ' ') {
154 cmd++;
155 }
156 int_4 N = strlen (cmd);
157 if (N > 0 && cmd[N - 1] == '\n') {
158 cmd[N - 1] = '\0';
159 }
160 option (cmd);
161 } else if (LEQUAL ("include", cmd)) {
162 RECORD fn;
163 (void) strtok (cmd, "'");
164 char *str = strtok (NO_TEXT, "'");
165 if (str != NO_TEXT) {
166 _srecordf (fn, "%s/%s", path, str);
167 get_source (fn, nest + 1);
168 } else {
169 FATAL (1708, "filename required", cmd);
170 }
171 } else {
172 FATAL (1709, "preprocessor directive", cmd);
173 }
174 }
© 2002-2025 J.M. van der Veer (jmvdveer@xs4all.nl)
|