Home | History | Annotate | Download | only in nasm
      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
     65 nil_listgen_init(char *p, efunc e)
     66 {
     67 }
     68 
     69 static void
     70 nil_listgen_cleanup(void)
     71 {
     72 }
     73 
     74 static void
     75 nil_listgen_output(long v, const void *d, unsigned long v2)
     76 {
     77 }
     78 
     79 static void
     80 nil_listgen_line(int v, char *p)
     81 {
     82 }
     83 
     84 static void
     85 nil_listgen_uplevel(int v)
     86 {
     87 }
     88 
     89 static void
     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
    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 *
    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
    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 *
    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
    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
    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
    272 nasm_preproc_add_include_file(yasm_preproc *preproc, const char *filename)
    273 {
    274     pp_pre_include(filename);
    275 }
    276 
    277 static void
    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
    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
    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
    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 *
    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