Home | History | Annotate | Download | only in libyasm
      1 /*
      2  * Value/Parameter type functions
      3  *
      4  *  Copyright (C) 2001-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-stdint.h"
     30 #include "coretype.h"
     31 #include "valparam.h"
     32 
     33 #include "errwarn.h"
     34 #include "intnum.h"
     35 #include "expr.h"
     36 #include "symrec.h"
     37 
     38 #include "section.h"
     39 
     40 void
     41 yasm_call_directive(const yasm_directive *directive, yasm_object *object,
     42                     yasm_valparamhead *valparams,
     43                     yasm_valparamhead *objext_valparams, unsigned long line)
     44 {
     45     yasm_valparam *vp;
     46 
     47     if ((directive->flags & (YASM_DIR_ARG_REQUIRED|YASM_DIR_ID_REQUIRED)) &&
     48         (!valparams || !yasm_vps_first(valparams))) {
     49         yasm_error_set(YASM_ERROR_SYNTAX,
     50                        N_("directive `%s' requires an argument"),
     51                        directive->name);
     52         return;
     53     }
     54     if (valparams) {
     55         vp = yasm_vps_first(valparams);
     56         if ((directive->flags & YASM_DIR_ID_REQUIRED) &&
     57             vp->type != YASM_PARAM_ID) {
     58             yasm_error_set(YASM_ERROR_SYNTAX,
     59                 N_("directive `%s' requires an identifier parameter"),
     60                 directive->name);
     61             return;
     62         }
     63     }
     64     directive->handler(object, valparams, objext_valparams, line);
     65 }
     66 
     67 yasm_valparam *
     68 yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix)
     69 {
     70     yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
     71     r->val = v;
     72     r->type = YASM_PARAM_ID;
     73     r->param.id = p;
     74     r->id_prefix = (char)id_prefix;
     75     return r;
     76 }
     77 
     78 yasm_valparam *
     79 yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p)
     80 {
     81     yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
     82     r->val = v;
     83     r->type = YASM_PARAM_STRING;
     84     r->param.str = p;
     85     r->id_prefix = '\0';
     86     return r;
     87 }
     88 
     89 yasm_valparam *
     90 yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p)
     91 {
     92     yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
     93     r->val = v;
     94     r->type = YASM_PARAM_EXPR;
     95     r->param.e = p;
     96     r->id_prefix = '\0';
     97     return r;
     98 }
     99 
    100 /*@null@*/ /*@only@*/ yasm_expr *
    101 yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line)
    102 {
    103     if (!vp)
    104         return NULL;
    105     switch (vp->type) {
    106         case YASM_PARAM_ID:
    107             return yasm_expr_create_ident(yasm_expr_sym(
    108                 yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line);
    109         case YASM_PARAM_EXPR:
    110             return yasm_expr_copy(vp->param.e);
    111         default:
    112             return NULL;
    113     }
    114 }
    115 
    116 /*@null@*/ /*@dependent@*/ const char *
    117 yasm_vp_string(const yasm_valparam *vp)
    118 {
    119     if (!vp)
    120         return NULL;
    121     switch (vp->type) {
    122         case YASM_PARAM_ID:
    123             return vp->param.id;
    124         case YASM_PARAM_STRING:
    125             return vp->param.str;
    126         default:
    127             return NULL;
    128     }
    129 }
    130 
    131 /*@null@*/ /*@dependent@*/ const char *
    132 yasm_vp_id(const yasm_valparam *vp)
    133 {
    134     if (!vp)
    135         return NULL;
    136     if (vp->type == YASM_PARAM_ID) {
    137         if (vp->param.id[0] == vp->id_prefix)
    138             return &vp->param.id[1];
    139         else
    140             return vp->param.id;
    141     }
    142     return NULL;
    143 }
    144 
    145 void
    146 yasm_vps_delete(yasm_valparamhead *headp)
    147 {
    148     yasm_valparam *cur, *next;
    149 
    150     cur = STAILQ_FIRST(headp);
    151     while (cur) {
    152         next = STAILQ_NEXT(cur, link);
    153         if (cur->val)
    154             yasm_xfree(cur->val);
    155         switch (cur->type) {
    156             case YASM_PARAM_ID:
    157                 yasm_xfree(cur->param.id);
    158                 break;
    159             case YASM_PARAM_STRING:
    160                 yasm_xfree(cur->param.str);
    161                 break;
    162             case YASM_PARAM_EXPR:
    163                 yasm_expr_destroy(cur->param.e);
    164                 break;
    165         }
    166         yasm_xfree(cur);
    167         cur = next;
    168     }
    169     STAILQ_INIT(headp);
    170 }
    171 
    172 void
    173 yasm_vps_print(const yasm_valparamhead *headp, FILE *f)
    174 {
    175     const yasm_valparam *vp;
    176 
    177     if(!headp) {
    178         fprintf(f, "(none)");
    179         return;
    180     }
    181 
    182     yasm_vps_foreach(vp, headp) {
    183         if (vp->val)
    184             fprintf(f, "(\"%s\",", vp->val);
    185         else
    186             fprintf(f, "((nil),");
    187         switch (vp->type) {
    188             case YASM_PARAM_ID:
    189                 fprintf(f, "%s", vp->param.id);
    190                 break;
    191             case YASM_PARAM_STRING:
    192                 fprintf(f, "\"%s\"", vp->param.str);
    193                 break;
    194             case YASM_PARAM_EXPR:
    195                 yasm_expr_print(vp->param.e, f);
    196                 break;
    197         }
    198         fprintf(f, ")");
    199         if (yasm_vps_next(vp))
    200             fprintf(f, ",");
    201     }
    202 }
    203 
    204 yasm_valparamhead *
    205 yasm_vps_create(void)
    206 {
    207     yasm_valparamhead *headp = yasm_xmalloc(sizeof(yasm_valparamhead));
    208     yasm_vps_initialize(headp);
    209     return headp;
    210 }
    211 
    212 void
    213 yasm_vps_destroy(yasm_valparamhead *headp)
    214 {
    215     yasm_vps_delete(headp);
    216     yasm_xfree(headp);
    217 }
    218 
    219 int
    220 yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
    221                 const yasm_dir_help *help, size_t nhelp, void *data,
    222                 int (*helper_valparam) (void *obj, yasm_valparam *vp,
    223                                         unsigned long line, void *data))
    224 {
    225     yasm_valparam *vp = vp_first;
    226     int anymatched = 0;
    227     int matched;
    228 
    229     if (!vp)
    230         return 0;
    231 
    232     do {
    233         const char *s;
    234         size_t i;
    235 
    236         matched = 0;
    237         if (!vp->val && (s = yasm_vp_id(vp))) {
    238             for (i=0; i<nhelp; i++) {
    239                 if (help[i].needsparam == 0 &&
    240                     yasm__strcasecmp(s, help[i].name) == 0) {
    241                     if (help[i].helper(obj, vp, line,
    242                                        ((char *)data)+help[i].off,
    243                                        help[i].arg) != 0)
    244                         return -1;
    245                     matched = 1;
    246                     anymatched = 1;
    247                     break;
    248                 }
    249             }
    250         } else if (vp->val) {
    251             for (i=0; i<nhelp; i++) {
    252                 if (help[i].needsparam == 1 &&
    253                     yasm__strcasecmp(vp->val, help[i].name) == 0) {
    254                     if (help[i].helper(obj, vp, line,
    255                                        ((char *)data)+help[i].off,
    256                                        help[i].arg) != 0)
    257                         return -1;
    258                     matched = 1;
    259                     anymatched = 1;
    260                     break;
    261                 }
    262             }
    263         }
    264 
    265         if (!matched) {
    266             int final = helper_valparam(obj, vp, line, data);
    267             if (final < 0)
    268                 return -1;
    269             if (final > 0)
    270                 anymatched = 1;
    271         }
    272     } while((vp = yasm_vps_next(vp)));
    273 
    274     return anymatched;
    275 }
    276 
    277 int
    278 yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
    279                         void *d, uintptr_t flag)
    280 {
    281     unsigned long *flags = (unsigned long *)d;
    282     *flags |= flag;
    283     return 0;
    284 }
    285 
    286 int
    287 yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
    288                          void *d, uintptr_t flag)
    289 {
    290     unsigned long *flags = (unsigned long *)d;
    291     *flags &= ~flag;
    292     return 0;
    293 }
    294 
    295 int
    296 yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
    297                          void *d, uintptr_t flag)
    298 {
    299     unsigned long *flags = (unsigned long *)d;
    300     *flags = flag;
    301     return 0;
    302 }
    303 
    304 int
    305 yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
    306                      void *data, uintptr_t arg)
    307 {
    308     yasm_object *object = (yasm_object *)obj;
    309     yasm_expr **expr = (yasm_expr **)data;
    310 
    311     if (*expr)
    312         yasm_expr_destroy(*expr);
    313     if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) {
    314         yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"),
    315                        vp->val);
    316         return -1;
    317     }
    318     return 0;
    319 }
    320 
    321 int
    322 yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
    323                      void *data, uintptr_t arg)
    324 {
    325     yasm_object *object = (yasm_object *)obj;
    326     /*@only@*/ /*@null@*/ yasm_expr *e;
    327     /*@dependent@*/ /*@null@*/ yasm_intnum *local;
    328     yasm_intnum **intn = (yasm_intnum **)data;
    329 
    330     if (*intn)
    331         yasm_intnum_destroy(*intn);
    332     if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
    333         !(local = yasm_expr_get_intnum(&e, 0))) {
    334         yasm_error_set(YASM_ERROR_NOT_CONSTANT,
    335                        N_("argument to `%s' is not an integer"),
    336                        vp->val);
    337         if (e)
    338             yasm_expr_destroy(e);
    339         return -1;
    340     }
    341     *intn = yasm_intnum_copy(local);
    342     yasm_expr_destroy(e);
    343     return 0;
    344 }
    345 
    346 int
    347 yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
    348                        void *data, uintptr_t arg)
    349 {
    350     /*@dependent@*/ /*@null@*/ const char *local;
    351     char **s = (char **)data;
    352 
    353     if (*s)
    354         yasm_xfree(*s);
    355     if (!(local = yasm_vp_string(vp))) {
    356         yasm_error_set(YASM_ERROR_VALUE,
    357                        N_("argument to `%s' is not a string or identifier"),
    358                        vp->val);
    359         return -1;
    360     }
    361     *s = yasm__xstrdup(local);
    362     return 0;
    363 }
    364 
    365 int
    366 yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
    367                               unsigned long line, void *data)
    368 {
    369     const char *s;
    370 
    371     if (vp->val) {
    372         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
    373                       vp->val);
    374         return 0;
    375     }
    376 
    377     if ((s = yasm_vp_id(vp)))
    378         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s);
    379     else if (vp->type == YASM_PARAM_STRING)
    380         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier"));
    381     else
    382         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier"));
    383 
    384     return 0;
    385 }
    386