Home | History | Annotate | Download | only in libyasm
      1 /**
      2  * \file libyasm/valparam.h
      3  * \brief YASM value/parameter interface.
      4  *
      5  * \license
      6  *  Copyright (C) 2001-2007  Peter Johnson
      7  *
      8  * Redistribution and use in source and binary forms, with or without
      9  * modification, are permitted provided that the following conditions
     10  * are met:
     11  *  - Redistributions of source code must retain the above copyright
     12  *    notice, this list of conditions and the following disclaimer.
     13  *  - Redistributions in binary form must reproduce the above copyright
     14  *    notice, this list of conditions and the following disclaimer in the
     15  *    documentation and/or other materials provided with the distribution.
     16  *
     17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
     18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
     21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27  * POSSIBILITY OF SUCH DAMAGE.
     28  * \endlicense
     29  */
     30 #ifndef YASM_VALPARAM_H
     31 #define YASM_VALPARAM_H
     32 
     33 #ifndef YASM_LIB_DECL
     34 #define YASM_LIB_DECL
     35 #endif
     36 
     37 /** Value/parameter pair.  \internal */
     38 struct yasm_valparam {
     39     /*@reldef@*/ STAILQ_ENTRY(yasm_valparam) link;  /**< Next pair in list */
     40     /*@owned@*/ /*@null@*/ char *val;           /**< Value */
     41 
     42     /** Parameter type. */
     43     enum yasm_param_type {
     44         YASM_PARAM_ID,                          /**< Identifier */
     45         YASM_PARAM_STRING,                      /**< String */
     46         YASM_PARAM_EXPR                         /**< Expression */
     47     } type;                                     /**< Parameter type */
     48 
     49     /** Parameter value. */
     50     union yasm_param {
     51         /*@owned@*/ char *id;                   /**< Identifier */
     52         /*@owned@*/ char *str;                  /**< String */
     53         /*@owned@*/ yasm_expr *e;               /**< Expression */
     54     } param;                                    /**< Parameter */
     55 
     56     /** Prefix character that indicates a raw identifier.  When
     57      * yasm_vp_string() is called on a #YASM_PARAM_ID, all characters are
     58      * returned.  When yasm_vp_id() is called on a #YASM_PARAM_ID, if the
     59      * identifier begins with this character, this character is stripped
     60      * from the returned value.
     61      */
     62     char id_prefix;
     63 };
     64 
     65 /** Linked list of value/parameter pairs.  \internal */
     66 /*@reldef@*/ STAILQ_HEAD(yasm_valparamhead, yasm_valparam);
     67 
     68 /** Directive list entry structure. */
     69 struct yasm_directive {
     70     /** Directive name.  GAS directives should include the ".", NASM
     71      * directives should just be the raw name (not including the []).
     72      * NULL entry required to terminate list of directives.
     73      */
     74     /*@null@*/ const char *name;
     75 
     76     const char *parser;                     /**< Parser keyword */
     77 
     78     /** Handler callback function for the directive.
     79      * \param object            object
     80      * \param valparams         value/parameters
     81      * \param objext_valparams  object format-specific value/parameters
     82      * \param line              virtual line (from yasm_linemap)
     83      */
     84     void (*handler) (yasm_object *object, yasm_valparamhead *valparams,
     85                      yasm_valparamhead *objext_valparams, unsigned long line);
     86 
     87     /** Flags for pre-handler parameter checking. */
     88     enum yasm_directive_flags {
     89         YASM_DIR_ANY = 0,           /**< Any valparams accepted */
     90         YASM_DIR_ARG_REQUIRED = 1,  /**< Require at least 1 valparam */
     91         YASM_DIR_ID_REQUIRED = 2    /**< First valparam must be ID */
     92     } flags;
     93 };
     94 
     95 /** Call a directive.  Performs any valparam checks asked for by the
     96  * directive prior to call.  Note that for a variety of reasons, a directive
     97  * can generate an error.
     98  * \param directive             directive
     99  * \param object                object
    100  * \param valparams             value/parameters
    101  * \param objext_valparams      object format-specific value/parameters
    102  * \param line                  virtual line (from yasm_linemap)
    103  */
    104 YASM_LIB_DECL
    105 void yasm_call_directive(const yasm_directive *directive, yasm_object *object,
    106                          yasm_valparamhead *valparams,
    107                          yasm_valparamhead *objext_valparams,
    108                          unsigned long line);
    109 
    110 /** Create a new valparam with identifier parameter.
    111  * \param v             value
    112  * \param p             parameter
    113  * \param id_prefix     identifier prefix for raw identifiers
    114  * \return Newly allocated valparam.
    115  */
    116 YASM_LIB_DECL
    117 yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p,
    118                                  int id_prefix);
    119 
    120 /** Create a new valparam with string parameter.
    121  * \param v     value
    122  * \param p     parameter
    123  * \return Newly allocated valparam.
    124  */
    125 YASM_LIB_DECL
    126 yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p);
    127 
    128 /** Create a new valparam with expression parameter.
    129  * \param v     value
    130  * \param p     parameter
    131  * \return Newly allocated valparam.
    132  */
    133 YASM_LIB_DECL
    134 yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v,
    135                                    /*@keep@*/ yasm_expr *p);
    136 
    137 /** Get a valparam parameter as an expr.  If the parameter is an identifier,
    138  * it's treated as a symbol (yasm_symtab_use() is called to convert it).
    139  * \param vp            valparam
    140  * \param symtab        symbol table
    141  * \param line          virtual line
    142  * \return Expression, or NULL if vp is NULL or the parameter cannot be
    143  *         converted to an expression.
    144  */
    145 YASM_LIB_DECL
    146 /*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr
    147     (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line);
    148 
    149 /** Get a valparam parameter as a string.  If the parameter is an identifier,
    150  * it's treated as a string.
    151  * \param vp            valparam
    152  * \return String, or NULL if vp is NULL or the parameter cannot be realized
    153  *         as a string.
    154  */
    155 YASM_LIB_DECL
    156 /*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp);
    157 
    158 /** Get a valparam parameter as an identifier.
    159  * \param vp            valparam
    160  * \return Identifier (string), or NULL if vp is NULL or the parameter is not
    161  *         an identifier.
    162  */
    163 YASM_LIB_DECL
    164 /*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp);
    165 
    166 /** Create a new linked list of valparams.
    167  * \return Newly allocated valparam list.
    168  */
    169 YASM_LIB_DECL
    170 yasm_valparamhead *yasm_vps_create(void);
    171 
    172 /** Destroy a list of valparams (created with yasm_vps_create).
    173  * \param headp         list of valparams
    174  */
    175 YASM_LIB_DECL
    176 void yasm_vps_destroy(yasm_valparamhead *headp);
    177 
    178 /** Initialize linked list of valparams.
    179  * \param headp linked list
    180  */
    181 void yasm_vps_initialize(/*@out@*/ yasm_valparamhead *headp);
    182 #ifndef YASM_DOXYGEN
    183 #define yasm_vps_initialize(headp)      STAILQ_INIT(headp)
    184 #endif
    185 
    186 /** Destroy (free allocated memory for) linked list of valparams (created with
    187  * yasm_vps_initialize).
    188  * \warning Deletes val/params.
    189  * \param headp linked list
    190  */
    191 YASM_LIB_DECL
    192 void yasm_vps_delete(yasm_valparamhead *headp);
    193 
    194 /** Append valparam to tail of linked list.
    195  * \param headp linked list
    196  * \param vp    valparam
    197  */
    198 void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp);
    199 #ifndef YASM_DOXYGEN
    200 #define yasm_vps_append(headp, vp)      do {        \
    201         if (vp)                                     \
    202             STAILQ_INSERT_TAIL(headp, vp, link);    \
    203     } while(0)
    204 #endif
    205 
    206 /** Get first valparam in linked list.
    207  * \param headp linked list
    208  * \return First valparam in linked list.
    209  */
    210 /*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_first
    211     (yasm_valparamhead *headp);
    212 #ifndef YASM_DOXYGEN
    213 #define yasm_vps_first(headp)       STAILQ_FIRST(headp)
    214 #endif
    215 
    216 /** Get next valparam in linked list.
    217  * \param cur   previous valparam in linked list
    218  * \return Next valparam in linked list.
    219  */
    220 /*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_next(yasm_valparam *cur);
    221 #ifndef YASM_DOXYGEN
    222 #define yasm_vps_next(cur)          STAILQ_NEXT(cur, link)
    223 #endif
    224 
    225 /** Iterate through linked list of valparams.
    226  * \internal
    227  * \param iter      iterator variable
    228  * \param headp     linked list
    229  */
    230 #ifndef YASM_DOXYGEN
    231 #define yasm_vps_foreach(iter, headp)   STAILQ_FOREACH(iter, headp, link)
    232 #endif
    233 
    234 /** Print linked list of valparams.  For debugging purposes.
    235  * \param f     file
    236  * \param headp linked list
    237  */
    238 YASM_LIB_DECL
    239 void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f);
    240 
    241 /** Directive valparam parse helper structure. */
    242 typedef struct yasm_dir_help {
    243     /** Value portion of val=param (if needsparam=1), or standalone identifier
    244      * (if needsparam=0).
    245      */
    246     const char *name;
    247 
    248     /** 1 if value requires parameter, 0 if it must not have a parameter. */
    249     int needsparam;
    250 
    251     /** Helper callback function if name and parameter existence match.
    252      * \param obj       obj passed into yasm_dir_helper()
    253      * \param vp        value/parameter
    254      * \param line      line passed into yasm_dir_helper()
    255      * \param data      data passed into yasm_dir_helper() plus
    256                         #yasm_dir_help.off offset
    257      * \param arg       #yasm_dir_help.arg argument
    258      * \return -1 on error, 0 otherwise.
    259      */
    260     int (*helper) (void *obj, yasm_valparam *vp, unsigned long line,
    261                    void *data, uintptr_t arg);
    262 
    263     /** Offset added to data pointer passed into yasm_dir_helper() before
    264      * data pointer is given to #yasm_dir_help.helper().  This is so that
    265      * a structure can be passed into yasm_dir_helper() and this can be an
    266      * offsetof() to point the helper function to a specific structure
    267      * member.
    268      */
    269     size_t off;
    270 
    271     /** Argument to pass in as the arg parameter to #yasm_dir_help.helper().
    272      */
    273     uintptr_t arg;
    274 } yasm_dir_help;
    275 
    276 /** Help parse a list of directive value/parameters.  Takes an array of
    277  * #yasm_dir_help structures and tries to match val=param (or just val)
    278  * against the passed value/parameters.  When no match is found in the
    279  * array of help structures, calls helper_valparam.
    280  * \param obj       object to be passed to yasm_dir_help.helper() or
    281  *                  helper_valparam() callback
    282  * \param vp_first  first value/parameter to examine
    283  * \param line      virtual line number; passed down to helper callback
    284  * \param help      array of #yasm_dir_help structures
    285  * \param nhelp     number of array elements
    286  * \param data      base data pointer; if a match is found,
    287  *                  the respective #yasm_dir_help.off is added to this
    288  *                  prior to it being passed to the helper callback
    289  * \param helper_valparam   catch-all callback; should return -1 on error,
    290  *                          0 if not matched, 1 if matched.
    291  * \return -1 on error, 1 if any arguments matched (including via
    292  *         catch-all callback), 0 if no match.
    293  */
    294 YASM_LIB_DECL
    295 int yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
    296                     const yasm_dir_help *help, size_t nhelp, void *data,
    297                     int (*helper_valparam) (void *object,
    298                                             yasm_valparam *vp,
    299                                             unsigned long line,
    300                                             void *data));
    301 
    302 /** Standard helper for yasm_dir_helper() that simply sets a flag when called.
    303  * It does not look at the vp; rather, it uses the value of the arg parameter,
    304  * and stores an unsigned long value to data.
    305  * \param obj   unused
    306  * \param vp    unused
    307  * \param line  unused
    308  * \param data  pointer to an unsigned long
    309  * \param arg   flag to set
    310  * \return 0
    311  */
    312 YASM_LIB_DECL
    313 int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
    314                              void *data, uintptr_t arg);
    315 
    316 /** Standard helper for yasm_dir_helper() that simply ORs a flag when called.
    317  * It does not look at the vp; rather, it uses the value of the arg parameter,
    318  * and ORs it with the unsigned long value in data.
    319  * \param obj   unused
    320  * \param vp    unused
    321  * \param line  unused
    322  * \param data  pointer to an unsigned long
    323  * \param arg   flag to OR
    324  * \return 0
    325  */
    326 YASM_LIB_DECL
    327 int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
    328                             void *data, uintptr_t arg);
    329 
    330 /** Standard helper for yasm_dir_helper() that simply ANDs a flag when called.
    331  * It does not look at the vp; rather, it uses the value of the arg parameter,
    332  * and ANDs its inverse (~) with the unsigned long value in data.
    333  * \param obj   unused
    334  * \param vp    unused
    335  * \param line  unused
    336  * \param data  pointer to an unsigned long
    337  * \param arg   flag to AND
    338  * \return 0
    339  */
    340 YASM_LIB_DECL
    341 int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
    342                              void *data, uintptr_t arg);
    343 
    344 /** Standard helper for yasm_dir_helper() that parses an expr parameter.
    345  * The #yasm_dir_help structure that uses this function should have
    346  * needsparam=1.  The obj parameter to yasm_dir_helper() when this helper
    347  * is used MUST point to a #yasm_object.  In addition, the data parameter
    348  * that is ultimately passed to this function (e.g. yasm_dir_helper() data
    349  * parameter plus #yasm_dir_help.off) must point to a #yasm_expr *
    350  * initialized to NULL.
    351  * \param obj   object; must be #yasm_object
    352  * \param vp    valparam
    353  * \param line  virtual line number
    354  * \param data  pointer to #yasm_expr *
    355  * \param arg   unused argument
    356  * \return -1 on error, 0 otherwise.
    357  */
    358 YASM_LIB_DECL
    359 int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
    360                          void *data, uintptr_t arg);
    361 
    362 /** Standard helper for yasm_dir_helper() that parses an intnum parameter.
    363  * The #yasm_dir_help structure that uses this function should have
    364  * needsparam=1.  The obj parameter to yasm_dir_helper() when this helper
    365  * is used MUST point to a #yasm_object.  In addition, the data parameter
    366  * that is ultimately passed to this function (e.g. yasm_dir_helper() data
    367  * parameter plus #yasm_dir_help.off) must point to a #yasm_intnum *
    368  * initialized to NULL.
    369  * \param obj   object; must be #yasm_object
    370  * \param vp    valparam
    371  * \param line  virtual line number
    372  * \param data  pointer to #yasm_intnum *
    373  * \param arg   unused argument
    374  * \return -1 on error, 0 otherwise.
    375  */
    376 YASM_LIB_DECL
    377 int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
    378                          void *data, uintptr_t arg);
    379 
    380 /** Standard helper for yasm_dir_helper() that parses an string (or
    381  * standalone identifier) parameter.
    382  * The #yasm_dir_help structure that uses this function should have
    383  * needsparam=1.  The data parameter that is ultimately passed to this
    384  * function (e.g. yasm_dir_helper() data parameter plus #yasm_dir_help.off)
    385  * must point to a char * initialized to NULL.
    386  * \param obj   unused
    387  * \param vp    valparam
    388  * \param line  unused
    389  * \param data  pointer to char *
    390  * \param arg   unused
    391  * \return -1 on error, 0 otherwise.
    392  */
    393 YASM_LIB_DECL
    394 int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
    395                            void *data, uintptr_t arg);
    396 
    397 /** Standard catch-all callback fro yasm_dir_helper().  Generates standard
    398  * warning for all valparams.
    399  * \param obj   unused
    400  * \param vp    valparam
    401  * \param line  unused
    402  * \param data  unused
    403  * \return 0
    404  */
    405 YASM_LIB_DECL
    406 int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
    407                                   unsigned long line, void *data);
    408 #endif
    409