1 /*
2 * Imported NASM preprocessor - glue code
3 *
4 * Copyright (C) 2002-2007 Peter Johnson
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25 * POSSIBILITY OF SUCH DAMAGE.
26 */
27 #include <util.h>
28
29 #include <libyasm.h>
30
31 #include "nasm.h"
32 #include "nasmlib.h"
33 #include "nasm-pp.h"
34 #include "nasm-eval.h"
35
36 typedef struct yasm_preproc_nasm {
37 yasm_preproc_base preproc; /* Base structure */
38
39 FILE *in;
40 char *line;
41 char *file_name;
42 long prior_linnum;
43 int lineinc;
44 } yasm_preproc_nasm;
45 yasm_symtab *nasm_symtab;
46 static yasm_linemap *cur_lm;
47 static yasm_errwarns *cur_errwarns;
48 int tasm_compatible_mode = 0;
49 int tasm_locals;
50 const char *tasm_segment;
51
52 #include "nasm-version.c"
53
54 typedef struct preproc_dep {
55 STAILQ_ENTRY(preproc_dep) link;
56 char *name;
57 } preproc_dep;
58
59 static STAILQ_HEAD(preproc_dep_head, preproc_dep) *preproc_deps;
60 static int done_dep_preproc;
61
62 yasm_preproc_module yasm_nasm_LTX_preproc;
63
64 static void
nil_listgen_init(char * p,efunc e)65 nil_listgen_init(char *p, efunc e)
66 {
67 }
68
69 static void
nil_listgen_cleanup(void)70 nil_listgen_cleanup(void)
71 {
72 }
73
74 static void
nil_listgen_output(long v,const void * d,unsigned long v2)75 nil_listgen_output(long v, const void *d, unsigned long v2)
76 {
77 }
78
79 static void
nil_listgen_line(int v,char * p)80 nil_listgen_line(int v, char *p)
81 {
82 }
83
84 static void
nil_listgen_uplevel(int v)85 nil_listgen_uplevel(int v)
86 {
87 }
88
89 static void
nil_listgen_downlevel(int v)90 nil_listgen_downlevel(int v)
91 {
92 }
93
94 static ListGen nil_list = {
95 nil_listgen_init,
96 nil_listgen_cleanup,
97 nil_listgen_output,
98 nil_listgen_line,
99 nil_listgen_uplevel,
100 nil_listgen_downlevel
101 };
102
103
104 static void
nasm_efunc(int severity,const char * fmt,...)105 nasm_efunc(int severity, const char *fmt, ...)
106 {
107 va_list va;
108
109 va_start(va, fmt);
110 switch (severity & ERR_MASK) {
111 case ERR_WARNING:
112 yasm_warn_set_va(YASM_WARN_PREPROC, fmt, va);
113 break;
114 case ERR_NONFATAL:
115 yasm_error_set_va(YASM_ERROR_GENERAL, fmt, va);
116 break;
117 case ERR_FATAL:
118 yasm_fatal(fmt, va);
119 /*@notreached@*/
120 break;
121 case ERR_PANIC:
122 yasm_internal_error(fmt); /* FIXME */
123 break;
124 case ERR_DEBUG:
125 break;
126 }
127 va_end(va);
128 yasm_errwarn_propagate(cur_errwarns,
129 yasm_linemap_poke(cur_lm, nasm_src_get_fname(),
130 (unsigned long)nasm_src_get_linnum()));
131 }
132
133 static yasm_preproc *
nasm_preproc_create(const char * in_filename,yasm_symtab * symtab,yasm_linemap * lm,yasm_errwarns * errwarns)134 nasm_preproc_create(const char *in_filename, yasm_symtab *symtab,
135 yasm_linemap *lm, yasm_errwarns *errwarns)
136 {
137 FILE *f;
138 yasm_preproc_nasm *preproc_nasm = yasm_xmalloc(sizeof(yasm_preproc_nasm));
139
140 preproc_nasm->preproc.module = &yasm_nasm_LTX_preproc;
141
142 if (strcmp(in_filename, "-") != 0) {
143 f = fopen(in_filename, "r");
144 if (!f)
145 yasm__fatal( N_("Could not open input file") );
146 }
147 else
148 f = stdin;
149
150 preproc_nasm->in = f;
151 nasm_symtab = symtab;
152 cur_lm = lm;
153 cur_errwarns = errwarns;
154 preproc_deps = NULL;
155 done_dep_preproc = 0;
156 preproc_nasm->line = NULL;
157 preproc_nasm->file_name = NULL;
158 preproc_nasm->prior_linnum = 0;
159 preproc_nasm->lineinc = 0;
160 nasmpp.reset(f, in_filename, 2, nasm_efunc, nasm_evaluate, &nil_list);
161
162 pp_extra_stdmac(nasm_version_mac);
163
164 return (yasm_preproc *)preproc_nasm;
165 }
166
167 static void
nasm_preproc_destroy(yasm_preproc * preproc)168 nasm_preproc_destroy(yasm_preproc *preproc)
169 {
170 yasm_preproc_nasm *preproc_nasm = (yasm_preproc_nasm *)preproc;
171 nasmpp.cleanup(0);
172 if (preproc_nasm->line)
173 yasm_xfree(preproc_nasm->line);
174 if (preproc_nasm->file_name)
175 yasm_xfree(preproc_nasm->file_name);
176 yasm_xfree(preproc);
177 if (preproc_deps)
178 yasm_xfree(preproc_deps);
179 }
180
181 static char *
nasm_preproc_get_line(yasm_preproc * preproc)182 nasm_preproc_get_line(yasm_preproc *preproc)
183 {
184 yasm_preproc_nasm *preproc_nasm = (yasm_preproc_nasm *)preproc;
185 long linnum;
186 int altline;
187 char *line;
188
189 if (preproc_nasm->line) {
190 char *retval = preproc_nasm->line;
191 preproc_nasm->line = NULL;
192 return retval;
193 }
194
195 line = nasmpp.getline();
196 if (!line)
197 {
198 nasmpp.cleanup(1);
199 return NULL; /* EOF */
200 }
201
202 linnum = preproc_nasm->prior_linnum += preproc_nasm->lineinc;
203 altline = nasm_src_get(&linnum, &preproc_nasm->file_name);
204 if (altline != 0) {
205 preproc_nasm->lineinc =
206 (altline != -1 || preproc_nasm->lineinc != 1);
207 preproc_nasm->line = line;
208 line = yasm_xmalloc(40+strlen(preproc_nasm->file_name));
209 sprintf(line, "%%line %ld+%d %s", linnum,
210 preproc_nasm->lineinc, preproc_nasm->file_name);
211 preproc_nasm->prior_linnum = linnum;
212 }
213
214 return line;
215 }
216
217 void
nasm_preproc_add_dep(char * name)218 nasm_preproc_add_dep(char *name)
219 {
220 preproc_dep *dep;
221
222 /* If not processing dependencies, simply return */
223 if (!preproc_deps)
224 return;
225
226 /* Save in preproc_deps */
227 dep = yasm_xmalloc(sizeof(preproc_dep));
228 dep->name = yasm__xstrdup(name);
229 STAILQ_INSERT_TAIL(preproc_deps, dep, link);
230 }
231
232 static size_t
nasm_preproc_get_included_file(yasm_preproc * preproc,char * buf,size_t max_size)233 nasm_preproc_get_included_file(yasm_preproc *preproc, /*@out@*/ char *buf,
234 size_t max_size)
235 {
236 if (!preproc_deps) {
237 preproc_deps = yasm_xmalloc(sizeof(struct preproc_dep_head));
238 STAILQ_INIT(preproc_deps);
239 }
240
241 for (;;) {
242 char *line;
243
244 /* Pull first dep out of preproc_deps and return it if there is one */
245 if (!STAILQ_EMPTY(preproc_deps)) {
246 char *name;
247 preproc_dep *dep = STAILQ_FIRST(preproc_deps);
248 STAILQ_REMOVE_HEAD(preproc_deps, link);
249 name = dep->name;
250 yasm_xfree(dep);
251 strncpy(buf, name, max_size);
252 buf[max_size-1] = '\0';
253 yasm_xfree(name);
254 return strlen(buf);
255 }
256
257 /* No more preprocessing to do */
258 if (done_dep_preproc) {
259 return 0;
260 }
261
262 /* Preprocess some more, throwing away the result */
263 line = nasmpp.getline();
264 if (line)
265 yasm_xfree(line);
266 else
267 done_dep_preproc = 1;
268 }
269 }
270
271 static void
nasm_preproc_add_include_file(yasm_preproc * preproc,const char * filename)272 nasm_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
273 {
274 pp_pre_include(filename);
275 }
276
277 static void
nasm_preproc_predefine_macro(yasm_preproc * preproc,const char * macronameval)278 nasm_preproc_predefine_macro(yasm_preproc *preproc, const char *macronameval)
279 {
280 char *mnv = yasm__xstrdup(macronameval);
281 pp_pre_define(mnv);
282 yasm_xfree(mnv);
283 }
284
285 static void
nasm_preproc_undefine_macro(yasm_preproc * preproc,const char * macroname)286 nasm_preproc_undefine_macro(yasm_preproc *preproc, const char *macroname)
287 {
288 char *mn = yasm__xstrdup(macroname);
289 pp_pre_undefine(mn);
290 yasm_xfree(mn);
291 }
292
293 static void
nasm_preproc_define_builtin(yasm_preproc * preproc,const char * macronameval)294 nasm_preproc_define_builtin(yasm_preproc *preproc, const char *macronameval)
295 {
296 char *mnv = yasm__xstrdup(macronameval);
297 pp_builtin_define(mnv);
298 yasm_xfree(mnv);
299 }
300
301 static void
nasm_preproc_add_standard(yasm_preproc * preproc,const char ** macros)302 nasm_preproc_add_standard(yasm_preproc *preproc, const char **macros)
303 {
304 pp_extra_stdmac(macros);
305 }
306
307 /* Define preproc structure -- see preproc.h for details */
308 yasm_preproc_module yasm_nasm_LTX_preproc = {
309 "Real NASM Preprocessor",
310 "nasm",
311 nasm_preproc_create,
312 nasm_preproc_destroy,
313 nasm_preproc_get_line,
314 nasm_preproc_get_included_file,
315 nasm_preproc_add_include_file,
316 nasm_preproc_predefine_macro,
317 nasm_preproc_undefine_macro,
318 nasm_preproc_define_builtin,
319 nasm_preproc_add_standard
320 };
321
322 static yasm_preproc *
tasm_preproc_create(const char * in_filename,yasm_symtab * symtab,yasm_linemap * lm,yasm_errwarns * errwarns)323 tasm_preproc_create(const char *in_filename, yasm_symtab *symtab,
324 yasm_linemap *lm, yasm_errwarns *errwarns)
325 {
326 tasm_compatible_mode = 1;
327 return nasm_preproc_create(in_filename, symtab, lm, errwarns);
328 }
329
330 yasm_preproc_module yasm_tasm_LTX_preproc = {
331 "Real TASM Preprocessor",
332 "tasm",
333 tasm_preproc_create,
334 nasm_preproc_destroy,
335 nasm_preproc_get_line,
336 nasm_preproc_get_included_file,
337 nasm_preproc_add_include_file,
338 nasm_preproc_predefine_macro,
339 nasm_preproc_undefine_macro,
340 nasm_preproc_define_builtin,
341 nasm_preproc_add_standard
342 };
343