aboutsummaryrefslogtreecommitdiff
path: root/libyasm/valparam.h
blob: d7343d4955f6e62aa49039020e77e86a2c226fa8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
/**
 * \file libyasm/valparam.h
 * \brief YASM value/parameter interface.
 *
 * \license
 *  Copyright (C) 2001-2007  Peter Johnson
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *  - Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 * \endlicense
 */
#ifndef YASM_VALPARAM_H
#define YASM_VALPARAM_H

#ifndef YASM_LIB_DECL
#define YASM_LIB_DECL
#endif

/** Value/parameter pair.  \internal */
struct yasm_valparam {
    /*@reldef@*/ STAILQ_ENTRY(yasm_valparam) link;  /**< Next pair in list */
    /*@owned@*/ /*@null@*/ char *val;           /**< Value */

    /** Parameter type. */
    enum yasm_param_type {
        YASM_PARAM_ID,                          /**< Identifier */
        YASM_PARAM_STRING,                      /**< String */
        YASM_PARAM_EXPR                         /**< Expression */
    } type;                                     /**< Parameter type */

    /** Parameter value. */
    union yasm_param {
        /*@owned@*/ char *id;                   /**< Identifier */
        /*@owned@*/ char *str;                  /**< String */
        /*@owned@*/ yasm_expr *e;               /**< Expression */
    } param;                                    /**< Parameter */

    /** Prefix character that indicates a raw identifier.  When
     * yasm_vp_string() is called on a #YASM_PARAM_ID, all characters are
     * returned.  When yasm_vp_id() is called on a #YASM_PARAM_ID, if the
     * identifier begins with this character, this character is stripped
     * from the returned value.
     */
    char id_prefix;
};

/** Linked list of value/parameter pairs.  \internal */
/*@reldef@*/ STAILQ_HEAD(yasm_valparamhead, yasm_valparam);

/** Directive list entry structure. */
struct yasm_directive {
    /** Directive name.  GAS directives should include the ".", NASM
     * directives should just be the raw name (not including the []).
     * NULL entry required to terminate list of directives.
     */
    /*@null@*/ const char *name;

    const char *parser;                     /**< Parser keyword */

    /** Handler callback function for the directive.
     * \param object            object 
     * \param valparams         value/parameters
     * \param objext_valparams  object format-specific value/parameters
     * \param line              virtual line (from yasm_linemap)
     */
    void (*handler) (yasm_object *object, yasm_valparamhead *valparams,
                     yasm_valparamhead *objext_valparams, unsigned long line);

    /** Flags for pre-handler parameter checking. */
    enum yasm_directive_flags {
        YASM_DIR_ANY = 0,           /**< Any valparams accepted */
        YASM_DIR_ARG_REQUIRED = 1,  /**< Require at least 1 valparam */
        YASM_DIR_ID_REQUIRED = 2    /**< First valparam must be ID */
    } flags;
};

/** Call a directive.  Performs any valparam checks asked for by the
 * directive prior to call.  Note that for a variety of reasons, a directive
 * can generate an error.
 * \param directive             directive
 * \param object                object 
 * \param valparams             value/parameters
 * \param objext_valparams      object format-specific value/parameters
 * \param line                  virtual line (from yasm_linemap)
 */
YASM_LIB_DECL
void yasm_call_directive(const yasm_directive *directive, yasm_object *object,
                         yasm_valparamhead *valparams,
                         yasm_valparamhead *objext_valparams,
                         unsigned long line);

/** Create a new valparam with identifier parameter.
 * \param v             value
 * \param p             parameter
 * \param id_prefix     identifier prefix for raw identifiers
 * \return Newly allocated valparam.
 */
YASM_LIB_DECL
yasm_valparam *yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p,
                                 int id_prefix);

/** Create a new valparam with string parameter.
 * \param v     value
 * \param p     parameter
 * \return Newly allocated valparam.
 */
YASM_LIB_DECL
yasm_valparam *yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p);

/** Create a new valparam with expression parameter.
 * \param v     value
 * \param p     parameter
 * \return Newly allocated valparam.
 */
YASM_LIB_DECL
yasm_valparam *yasm_vp_create_expr(/*@keep@*/ char *v,
                                   /*@keep@*/ yasm_expr *p);

/** Get a valparam parameter as an expr.  If the parameter is an identifier,
 * it's treated as a symbol (yasm_symtab_use() is called to convert it).
 * \param vp            valparam
 * \param symtab        symbol table
 * \param line          virtual line
 * \return Expression, or NULL if vp is NULL or the parameter cannot be
 *         converted to an expression.
 */
YASM_LIB_DECL
/*@null@*/ /*@only@*/ yasm_expr *yasm_vp_expr
    (const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line);

/** Get a valparam parameter as a string.  If the parameter is an identifier,
 * it's treated as a string.
 * \param vp            valparam
 * \return String, or NULL if vp is NULL or the parameter cannot be realized
 *         as a string.
 */
YASM_LIB_DECL
/*@null@*/ /*@dependent@*/ const char *yasm_vp_string(const yasm_valparam *vp);

/** Get a valparam parameter as an identifier.
 * \param vp            valparam
 * \return Identifier (string), or NULL if vp is NULL or the parameter is not
 *         an identifier.
 */
YASM_LIB_DECL
/*@null@*/ /*@dependent@*/ const char *yasm_vp_id(const yasm_valparam *vp);

/** Create a new linked list of valparams.
 * \return Newly allocated valparam list.
 */
YASM_LIB_DECL
yasm_valparamhead *yasm_vps_create(void);

/** Destroy a list of valparams (created with yasm_vps_create).
 * \param headp         list of valparams
 */
YASM_LIB_DECL
void yasm_vps_destroy(yasm_valparamhead *headp);

/** Initialize linked list of valparams.
 * \param headp linked list
 */
void yasm_vps_initialize(/*@out@*/ yasm_valparamhead *headp);
#ifndef YASM_DOXYGEN
#define yasm_vps_initialize(headp)      STAILQ_INIT(headp)
#endif

/** Destroy (free allocated memory for) linked list of valparams (created with
 * yasm_vps_initialize).
 * \warning Deletes val/params.
 * \param headp linked list
 */
YASM_LIB_DECL
void yasm_vps_delete(yasm_valparamhead *headp);

/** Append valparam to tail of linked list.
 * \param headp linked list
 * \param vp    valparam
 */
void yasm_vps_append(yasm_valparamhead *headp, /*@keep@*/ yasm_valparam *vp);
#ifndef YASM_DOXYGEN
#define yasm_vps_append(headp, vp)      do {        \
        if (vp)                                     \
            STAILQ_INSERT_TAIL(headp, vp, link);    \
    } while(0)
#endif

/** Get first valparam in linked list.
 * \param headp linked list
 * \return First valparam in linked list.
 */
/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_first
    (yasm_valparamhead *headp);
#ifndef YASM_DOXYGEN
#define yasm_vps_first(headp)       STAILQ_FIRST(headp)
#endif

/** Get next valparam in linked list.
 * \param cur   previous valparam in linked list
 * \return Next valparam in linked list.
 */
/*@null@*/ /*@dependent@*/ yasm_valparam *yasm_vps_next(yasm_valparam *cur);
#ifndef YASM_DOXYGEN
#define yasm_vps_next(cur)          STAILQ_NEXT(cur, link)
#endif

/** Iterate through linked list of valparams.
 * \internal
 * \param iter      iterator variable
 * \param headp     linked list
 */
#ifndef YASM_DOXYGEN
#define yasm_vps_foreach(iter, headp)   STAILQ_FOREACH(iter, headp, link)
#endif

/** Print linked list of valparams.  For debugging purposes.
 * \param f     file
 * \param headp linked list
 */
YASM_LIB_DECL
void yasm_vps_print(/*@null@*/ const yasm_valparamhead *headp, FILE *f);

/** Directive valparam parse helper structure. */
typedef struct yasm_dir_help {
    /** Value portion of val=param (if needsparam=1), or standalone identifier
     * (if needsparam=0).
     */
    const char *name;

    /** 1 if value requires parameter, 0 if it must not have a parameter. */
    int needsparam;

    /** Helper callback function if name and parameter existence match.
     * \param obj       obj passed into yasm_dir_helper()
     * \param vp        value/parameter
     * \param line      line passed into yasm_dir_helper()
     * \param data      data passed into yasm_dir_helper() plus
                        #yasm_dir_help.off offset
     * \param arg       #yasm_dir_help.arg argument
     * \return -1 on error, 0 otherwise.
     */
    int (*helper) (void *obj, yasm_valparam *vp, unsigned long line,
                   void *data, uintptr_t arg);

    /** Offset added to data pointer passed into yasm_dir_helper() before
     * data pointer is given to #yasm_dir_help.helper().  This is so that
     * a structure can be passed into yasm_dir_helper() and this can be an
     * offsetof() to point the helper function to a specific structure
     * member.
     */
    size_t off;

    /** Argument to pass in as the arg parameter to #yasm_dir_help.helper().
     */
    uintptr_t arg;
} yasm_dir_help;

/** Help parse a list of directive value/parameters.  Takes an array of
 * #yasm_dir_help structures and tries to match val=param (or just val)
 * against the passed value/parameters.  When no match is found in the
 * array of help structures, calls helper_valparam.
 * \param obj       object to be passed to yasm_dir_help.helper() or
 *                  helper_valparam() callback
 * \param vp_first  first value/parameter to examine
 * \param line      virtual line number; passed down to helper callback
 * \param help      array of #yasm_dir_help structures
 * \param nhelp     number of array elements
 * \param data      base data pointer; if a match is found,
 *                  the respective #yasm_dir_help.off is added to this
 *                  prior to it being passed to the helper callback
 * \param helper_valparam   catch-all callback; should return -1 on error,
 *                          0 if not matched, 1 if matched.
 * \return -1 on error, 1 if any arguments matched (including via
 *         catch-all callback), 0 if no match.
 */
YASM_LIB_DECL
int yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
                    const yasm_dir_help *help, size_t nhelp, void *data,
                    int (*helper_valparam) (void *object,
                                            yasm_valparam *vp,
                                            unsigned long line,
                                            void *data));

/** Standard helper for yasm_dir_helper() that simply sets a flag when called.
 * It does not look at the vp; rather, it uses the value of the arg parameter,
 * and stores an unsigned long value to data.
 * \param obj   unused
 * \param vp    unused
 * \param line  unused
 * \param data  pointer to an unsigned long
 * \param arg   flag to set
 * \return 0
 */
YASM_LIB_DECL
int yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
                             void *data, uintptr_t arg);

/** Standard helper for yasm_dir_helper() that simply ORs a flag when called.
 * It does not look at the vp; rather, it uses the value of the arg parameter,
 * and ORs it with the unsigned long value in data.
 * \param obj   unused
 * \param vp    unused
 * \param line  unused
 * \param data  pointer to an unsigned long
 * \param arg   flag to OR
 * \return 0
 */
YASM_LIB_DECL
int yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
                            void *data, uintptr_t arg);

/** Standard helper for yasm_dir_helper() that simply ANDs a flag when called.
 * It does not look at the vp; rather, it uses the value of the arg parameter,
 * and ANDs its inverse (~) with the unsigned long value in data.
 * \param obj   unused
 * \param vp    unused
 * \param line  unused
 * \param data  pointer to an unsigned long
 * \param arg   flag to AND
 * \return 0
 */
YASM_LIB_DECL
int yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
                             void *data, uintptr_t arg);

/** Standard helper for yasm_dir_helper() that parses an expr parameter.
 * The #yasm_dir_help structure that uses this function should have
 * needsparam=1.  The obj parameter to yasm_dir_helper() when this helper
 * is used MUST point to a #yasm_object.  In addition, the data parameter
 * that is ultimately passed to this function (e.g. yasm_dir_helper() data
 * parameter plus #yasm_dir_help.off) must point to a #yasm_expr *
 * initialized to NULL.
 * \param obj   object; must be #yasm_object
 * \param vp    valparam
 * \param line  virtual line number
 * \param data  pointer to #yasm_expr *
 * \param arg   unused argument
 * \return -1 on error, 0 otherwise.
 */
YASM_LIB_DECL
int yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
                         void *data, uintptr_t arg);

/** Standard helper for yasm_dir_helper() that parses an intnum parameter.
 * The #yasm_dir_help structure that uses this function should have
 * needsparam=1.  The obj parameter to yasm_dir_helper() when this helper
 * is used MUST point to a #yasm_object.  In addition, the data parameter
 * that is ultimately passed to this function (e.g. yasm_dir_helper() data
 * parameter plus #yasm_dir_help.off) must point to a #yasm_intnum *
 * initialized to NULL.
 * \param obj   object; must be #yasm_object
 * \param vp    valparam
 * \param line  virtual line number
 * \param data  pointer to #yasm_intnum *
 * \param arg   unused argument
 * \return -1 on error, 0 otherwise.
 */
YASM_LIB_DECL
int yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
                         void *data, uintptr_t arg);

/** Standard helper for yasm_dir_helper() that parses an string (or
 * standalone identifier) parameter.
 * The #yasm_dir_help structure that uses this function should have
 * needsparam=1.  The data parameter that is ultimately passed to this
 * function (e.g. yasm_dir_helper() data parameter plus #yasm_dir_help.off)
 * must point to a char * initialized to NULL.
 * \param obj   unused
 * \param vp    valparam
 * \param line  unused
 * \param data  pointer to char *
 * \param arg   unused
 * \return -1 on error, 0 otherwise.
 */
YASM_LIB_DECL
int yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
                           void *data, uintptr_t arg);

/** Standard catch-all callback fro yasm_dir_helper().  Generates standard
 * warning for all valparams.
 * \param obj   unused
 * \param vp    valparam
 * \param line  unused
 * \param data  unused
 * \return 0
 */
YASM_LIB_DECL
int yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
                                  unsigned long line, void *data);
#endif