Mercurial > hg > index.cgi
annotate lwcc/cpp-main.c @ 577:e49d24f4a9a5
Correct bug in the object file output code leading to stack corruption
It turns out leaving a pointer to a stack allocated temporary in a
persistent data structure is not conducive to correct program operation.
Undo the export check setup in the object file output sequence so a
pointer to stack allocated memory is not left hanging when the function
returns. This seems to correct at least one mysterious crash bug, and
possibly others.
Thanks to Boisy Pitre for reporting the crash bug that led to this
discovery, as well as a previous crash bug that likely has the same
root cause.
Additional thanks to Ciaran Anscomb whose debugger wielding wizardry
revealed the exact location of this particular bit of unbrilliance.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sat, 03 Aug 2024 14:30:06 -0600 |
parents | a38542cf4cc6 |
children |
rev | line source |
---|---|
295 | 1 /* |
2 lwcc/cpp-main.c | |
3 | |
4 Copyright © 2013 William Astle | |
5 | |
6 This file is part of LWTOOLS. | |
7 | |
8 LWTOOLS is free software: you can redistribute it and/or modify it under the | |
9 terms of the GNU General Public License as published by the Free Software | |
10 Foundation, either version 3 of the License, or (at your option) any later | |
11 version. | |
12 | |
13 This program is distributed in the hope that it will be useful, but WITHOUT | |
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
16 more details. | |
17 | |
18 You should have received a copy of the GNU General Public License along with | |
19 this program. If not, see <http://www.gnu.org/licenses/>. | |
20 */ | |
21 | |
22 #include <errno.h> | |
23 #include <stdarg.h> | |
24 #include <stdio.h> | |
25 #include <stdlib.h> | |
26 #include <string.h> | |
313 | 27 #include <lw_alloc.h> |
295 | 28 #include <lw_stringlist.h> |
29 #include <lw_cmdline.h> | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
30 #include <lw_string.h> |
295 | 31 |
496
a38542cf4cc6
Make lwcc stuff compile (on Linux anyway)
William Astle <lost@l-w.ca>
parents:
313
diff
changeset
|
32 #include <version.h> |
a38542cf4cc6
Make lwcc stuff compile (on Linux anyway)
William Astle <lost@l-w.ca>
parents:
313
diff
changeset
|
33 |
295 | 34 #include "cpp.h" |
35 | |
36 int process_file(const char *); | |
37 static void do_error(const char *f, ...); | |
38 | |
39 /* command line option handling */ | |
40 #define PROGVER "lwcc-cpp from " PACKAGE_STRING | |
41 char *program_name; | |
42 | |
43 /* input files */ | |
44 lw_stringlist_t input_files; | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
45 lw_stringlist_t includedirs; |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
46 lw_stringlist_t sysincludedirs; |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
47 lw_stringlist_t macrolist; |
295 | 48 |
49 /* various flags */ | |
50 int trigraphs = 0; | |
51 char *output_file = NULL; | |
52 FILE *output_fp = NULL; | |
53 | |
54 static struct lw_cmdline_options options[] = | |
55 { | |
56 { "output", 'o', "FILE", 0, "Output to FILE"}, | |
57 { "include", 'i', "FILE", 0, "Pre-include FILE" }, | |
58 { "includedir", 'I', "PATH", 0, "Add entry to the user include path" }, | |
59 { "sincludedir", 'S', "PATH", 0, "Add entry to the system include path" }, | |
60 { "define", 'D', "SYM[=VAL]",0, "Automatically define SYM to be VAL (or 1)"}, | |
61 { "trigraphs", 0x100, NULL, 0, "Enable interpretation of trigraphs" }, | |
62 { 0 } | |
63 }; | |
64 | |
65 static int parse_opts(int key, char *arg, void *state) | |
66 { | |
67 switch (key) | |
68 { | |
69 case 'o': | |
70 if (output_file) | |
71 do_error("Output file specified more than once."); | |
72 output_file = arg; | |
73 break; | |
74 | |
75 case 0x100: | |
76 trigraphs = 1; | |
77 break; | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
78 |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
79 case 'I': |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
80 lw_stringlist_addstring(includedirs, arg); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
81 break; |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
82 |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
83 case 'S': |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
84 lw_stringlist_addstring(sysincludedirs, arg); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
85 break; |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
86 |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
87 case 'D': |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
88 lw_stringlist_addstring(macrolist, arg); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
89 break; |
295 | 90 |
91 case lw_cmdline_key_end: | |
92 break; | |
93 | |
94 case lw_cmdline_key_arg: | |
95 lw_stringlist_addstring(input_files, arg); | |
96 break; | |
97 | |
98 default: | |
99 return lw_cmdline_err_unknown; | |
100 } | |
101 return 0; | |
102 } | |
103 | |
104 static struct lw_cmdline_parser cmdline_parser = | |
105 { | |
106 options, | |
107 parse_opts, | |
108 "INPUTFILE", | |
109 "lwcc-cpp - C preprocessor for lwcc", | |
110 PROGVER | |
111 }; | |
112 | |
113 int main(int argc, char **argv) | |
114 { | |
115 program_name = argv[0]; | |
116 int retval = 0; | |
117 | |
118 input_files = lw_stringlist_create(); | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
119 includedirs = lw_stringlist_create(); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
120 sysincludedirs = lw_stringlist_create(); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
121 macrolist = lw_stringlist_create(); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
122 |
295 | 123 /* parse command line arguments */ |
124 lw_cmdline_parse(&cmdline_parser, argc, argv, 0, 0, NULL); | |
125 | |
126 /* set up output file */ | |
127 if (output_file == NULL || strcmp(output_file, "-") == 0) | |
128 { | |
129 output_fp = stdout; | |
130 } | |
131 else | |
132 { | |
133 output_fp = fopen(output_file, "wb"); | |
134 if (output_fp == NULL) | |
135 { | |
136 do_error("Failed to create output file %s: %s", output_file, strerror(errno)); | |
137 } | |
138 } | |
139 | |
140 if (lw_stringlist_nstrings(input_files) == 0) | |
141 { | |
142 /* if no input files, work on stdin */ | |
143 retval = process_file("-"); | |
144 } | |
145 else | |
146 { | |
147 char *s; | |
148 lw_stringlist_reset(input_files); | |
149 for (s = lw_stringlist_current(input_files); s; s = lw_stringlist_next(input_files)) | |
150 { | |
151 retval = process_file(s); | |
152 if (retval != 0) | |
153 break; | |
154 } | |
155 } | |
156 lw_stringlist_destroy(input_files); | |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
157 lw_stringlist_destroy(includedirs); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
158 lw_stringlist_destroy(sysincludedirs); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
159 lw_stringlist_destroy(macrolist); |
295 | 160 exit(retval); |
161 } | |
162 | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
163 static void print_line_marker(FILE *fp, int line, const char *fn, int flag) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
164 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
165 fprintf(fp, "\n# %d \"", line); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
166 while (*fn) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
167 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
168 if (*fn < 32 || *fn == 34 || *fn > 126) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
169 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
170 fprintf(fp, "\\%03o", *fn); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
171 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
172 else |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
173 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
174 fprintf(fp, "%c", *fn); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
175 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
176 fn++; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
177 } |
307
9e342c4e4b66
Added support for __LINE__, __FILE__, __DATE__, and __TIME__
William Astle <lost@l-w.ca>
parents:
306
diff
changeset
|
178 fprintf(fp, "\" %d", flag); |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
179 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
180 |
295 | 181 int process_file(const char *fn) |
182 { | |
183 struct preproc_info *pp; | |
304
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
295
diff
changeset
|
184 struct token *tok = NULL; |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
185 int last_line = 0; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
186 char *last_fn = NULL; |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
187 char *tstr; |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
188 |
295 | 189 pp = preproc_init(fn); |
190 if (!pp) | |
191 return -1; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
192 |
306
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
193 /* set up the include paths */ |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
194 lw_stringlist_reset(includedirs); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
195 for (tstr = lw_stringlist_current(includedirs); tstr; tstr = lw_stringlist_next(includedirs)) |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
196 { |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
197 preproc_add_include(pp, tstr, 0); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
198 } |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
199 |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
200 lw_stringlist_reset(sysincludedirs); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
201 for (tstr = lw_stringlist_current(sysincludedirs); tstr; tstr = lw_stringlist_next(sysincludedirs)) |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
202 { |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
203 preproc_add_include(pp, tstr, 1); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
204 } |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
205 |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
206 /* set up pre-defined macros */ |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
207 lw_stringlist_reset(macrolist); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
208 for (tstr = lw_stringlist_current(macrolist); tstr; tstr = lw_stringlist_next(macrolist)) |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
209 { |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
210 preproc_add_macro(pp, tstr); |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
211 } |
b08787e5b9f3
Add include search paths and command line macro definitions
William Astle <lost@l-w.ca>
parents:
305
diff
changeset
|
212 |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
213 print_line_marker(output_fp, 1, fn, 1); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
214 last_fn = lw_strdup(fn); |
295 | 215 for (;;) |
216 { | |
304
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
295
diff
changeset
|
217 tok = preproc_next(pp); |
295 | 218 if (tok -> ttype == TOK_EOF) |
219 break; | |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
220 if (strcmp(tok -> fn, last_fn) != 0) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
221 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
222 int lt = 1; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
223 if (tok -> lineno != 1) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
224 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
225 lt = 2; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
226 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
227 lw_free(last_fn); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
228 last_fn = lw_strdup(tok -> fn); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
229 last_line = tok -> lineno; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
230 print_line_marker(output_fp, last_line, last_fn, lt); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
231 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
232 else |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
233 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
234 while (tok -> lineno > last_line) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
235 { |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
236 fprintf(output_fp, "\n"); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
237 last_line++; |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
238 } |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
239 } |
295 | 240 token_print(tok, output_fp); |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
241 if (tok -> ttype == TOK_EOL) |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
242 last_line++; |
304
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
295
diff
changeset
|
243 token_free(tok); |
295 | 244 } |
304
d85d173ba120
Checkpoint lwcc development - preprocessor is runnable but nonfunctional
William Astle <lost@l-w.ca>
parents:
295
diff
changeset
|
245 token_free(tok); |
305
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
246 lw_free(last_fn); |
54f213c8fb81
Various bugfixes and output tuning
William Astle <lost@l-w.ca>
parents:
304
diff
changeset
|
247 // symtab_dump(pp); |
295 | 248 preproc_finish(pp); |
249 return 0; | |
250 } | |
251 | |
252 static void do_error(const char *f, ...) | |
253 { | |
254 va_list args; | |
255 va_start(args, f); | |
256 fprintf(stderr, "ERROR: "); | |
257 vfprintf(stderr, f, args); | |
258 va_end(args); | |
259 fprintf(stderr, "\n"); | |
260 exit(1); | |
261 } |