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