• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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