2 * \file libyasm/valparam.h
3 * \brief YASM value/parameter interface.
6 * Copyright (C) 2001-2007 Peter Johnson
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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.
30 #ifndef YASM_VALPARAM_H
31 #define YASM_VALPARAM_H
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 */
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 */
49 /** Parameter value. */
51 /*@owned@*/ char *id; /**< Identifier */
52 /*@owned@*/ char *str; /**< String */
53 /*@owned@*/ yasm_expr *e; /**< Expression */
54 } param; /**< Parameter */
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.
65 /** Linked list of value/parameter pairs. \internal */
66 /*@reldef@*/ STAILQ_HEAD(yasm_valparamhead, yasm_valparam);
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.
74 /*@null@*/ const char *name;
76 const char *parser; /**< Parser keyword */
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)
84 void (*handler) (yasm_object *object, yasm_valparamhead *valparams,
85 yasm_valparamhead *objext_valparams, unsigned long line);
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 */
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)
105 void yasm_call_directive(const yasm_directive *directive, yasm_object *object,
106 yasm_valparamhead *valparams,
107 yasm_valparamhead *objext_valparams,
110 /** Create a new valparam with identifier parameter.
113 * \param id_prefix identifier prefix for raw identifiers
114 * \return Newly allocated valparam.
117 yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p,
120 /** Create a new valparam with string parameter.
123 * \return Newly allocated valparam.
126 yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p);
128 /** Create a new valparam with expression parameter.
131 * \return Newly allocated valparam.
134 yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v,
135 /*@keep@*/ yasm_expr *p);
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).
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.
146 /*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr
147 (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line);
149 /** Get a valparam parameter as a string. If the parameter is an identifier,
150 * it's treated as a string.
152 * \return String, or NULL if vp is NULL or the parameter cannot be realized
156 /*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp);
158 /** Get a valparam parameter as an identifier.
160 * \return Identifier (string), or NULL if vp is NULL or the parameter is not
164 /*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp);
166 /** Create a new linked list of valparams.
167 * \return Newly allocated valparam list.
170 yasm_valparamhead *yasm_vps_create(void);
172 /** Destroy a list of valparams (created with yasm_vps_create).
173 * \param headp list of valparams
176 void yasm_vps_destroy(yasm_valparamhead *headp);
178 /** Initialize linked list of valparams.
179 * \param headp linked list
181 void yasm_vps_initialize(/*@out@*/ yasm_valparamhead *headp);
183 #define yasm_vps_initialize(headp) STAILQ_INIT(headp)
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
192 void yasm_vps_delete(yasm_valparamhead *headp);
194 /** Append valparam to tail of linked list.
195 * \param headp linked list
198 void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp);
200 #define yasm_vps_append(headp, vp) do { \
202 STAILQ_INSERT_TAIL(headp, vp, link); \
206 /** Get first valparam in linked list.
207 * \param headp linked list
208 * \return First valparam in linked list.
210 /*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_first
211 (yasm_valparamhead *headp);
213 #define yasm_vps_first(headp) STAILQ_FIRST(headp)
216 /** Get next valparam in linked list.
217 * \param cur previous valparam in linked list
218 * \return Next valparam in linked list.
220 /*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_next(yasm_valparam *cur);
222 #define yasm_vps_next(cur) STAILQ_NEXT(cur, link)
225 /** Iterate through linked list of valparams.
227 * \param iter iterator variable
228 * \param headp linked list
231 #define yasm_vps_foreach(iter, headp) STAILQ_FOREACH(iter, headp, link)
234 /** Print linked list of valparams. For debugging purposes.
236 * \param headp linked list
239 void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f);
241 /** Directive valparam parse helper structure. */
242 typedef struct yasm_dir_help {
243 /** Value portion of val=param (if needsparam=1), or standalone identifier
248 /** 1 if value requires parameter, 0 if it must not have a parameter. */
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.
260 int (*helper) (void *obj, yasm_valparam *vp, unsigned long line,
261 void *data, uintptr_t arg);
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
271 /** Argument to pass in as the arg parameter to #yasm_dir_help.helper().
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.
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,
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.
308 * \param data pointer to an unsigned long
309 * \param arg flag to set
313 int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
314 void *data, uintptr_t arg);
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.
322 * \param data pointer to an unsigned long
323 * \param arg flag to OR
327 int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
328 void *data, uintptr_t arg);
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.
336 * \param data pointer to an unsigned long
337 * \param arg flag to AND
341 int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
342 void *data, uintptr_t arg);
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
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.
359 int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
360 void *data, uintptr_t arg);
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
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.
377 int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
378 void *data, uintptr_t arg);
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.
389 * \param data pointer to char *
391 * \return -1 on error, 0 otherwise.
394 int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
395 void *data, uintptr_t arg);
397 /** Standard catch-all callback fro yasm_dir_helper(). Generates standard
398 * warning for all valparams.
406 int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
407 unsigned long line, void *data);