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