• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Value/Parameter type functions
3  *
4  *  Copyright (C) 2001-2007  Peter Johnson
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 #include "util.h"
28 
29 #include "libyasm-stdint.h"
30 #include "coretype.h"
31 #include "valparam.h"
32 
33 #include "errwarn.h"
34 #include "intnum.h"
35 #include "expr.h"
36 #include "symrec.h"
37 
38 #include "section.h"
39 
40 void
yasm_call_directive(const yasm_directive * directive,yasm_object * object,yasm_valparamhead * valparams,yasm_valparamhead * objext_valparams,unsigned long line)41 yasm_call_directive(const yasm_directive *directive, yasm_object *object,
42                     yasm_valparamhead *valparams,
43                     yasm_valparamhead *objext_valparams, unsigned long line)
44 {
45     yasm_valparam *vp;
46 
47     if ((directive->flags & (YASM_DIR_ARG_REQUIRED|YASM_DIR_ID_REQUIRED)) &&
48         (!valparams || !yasm_vps_first(valparams))) {
49         yasm_error_set(YASM_ERROR_SYNTAX,
50                        N_("directive `%s' requires an argument"),
51                        directive->name);
52         return;
53     }
54     if (valparams) {
55         vp = yasm_vps_first(valparams);
56         if ((directive->flags & YASM_DIR_ID_REQUIRED) &&
57             vp->type != YASM_PARAM_ID) {
58             yasm_error_set(YASM_ERROR_SYNTAX,
59                 N_("directive `%s' requires an identifier parameter"),
60                 directive->name);
61             return;
62         }
63     }
64     directive->handler(object, valparams, objext_valparams, line);
65 }
66 
67 yasm_valparam *
yasm_vp_create_id(char * v,char * p,int id_prefix)68 yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix)
69 {
70     yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
71     r->val = v;
72     r->type = YASM_PARAM_ID;
73     r->param.id = p;
74     r->id_prefix = (char)id_prefix;
75     return r;
76 }
77 
78 yasm_valparam *
yasm_vp_create_string(char * v,char * p)79 yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p)
80 {
81     yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
82     r->val = v;
83     r->type = YASM_PARAM_STRING;
84     r->param.str = p;
85     r->id_prefix = '\0';
86     return r;
87 }
88 
89 yasm_valparam *
yasm_vp_create_expr(char * v,yasm_expr * p)90 yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p)
91 {
92     yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
93     r->val = v;
94     r->type = YASM_PARAM_EXPR;
95     r->param.e = p;
96     r->id_prefix = '\0';
97     return r;
98 }
99 
100 /*@null@*/ /*@only@*/ yasm_expr *
yasm_vp_expr(const yasm_valparam * vp,yasm_symtab * symtab,unsigned long line)101 yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line)
102 {
103     if (!vp)
104         return NULL;
105     switch (vp->type) {
106         case YASM_PARAM_ID:
107             return yasm_expr_create_ident(yasm_expr_sym(
108                 yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line);
109         case YASM_PARAM_EXPR:
110             return yasm_expr_copy(vp->param.e);
111         default:
112             return NULL;
113     }
114 }
115 
116 /*@null@*/ /*@dependent@*/ const char *
yasm_vp_string(const yasm_valparam * vp)117 yasm_vp_string(const yasm_valparam *vp)
118 {
119     if (!vp)
120         return NULL;
121     switch (vp->type) {
122         case YASM_PARAM_ID:
123             return vp->param.id;
124         case YASM_PARAM_STRING:
125             return vp->param.str;
126         default:
127             return NULL;
128     }
129 }
130 
131 /*@null@*/ /*@dependent@*/ const char *
yasm_vp_id(const yasm_valparam * vp)132 yasm_vp_id(const yasm_valparam *vp)
133 {
134     if (!vp)
135         return NULL;
136     if (vp->type == YASM_PARAM_ID) {
137         if (vp->param.id[0] == vp->id_prefix)
138             return &vp->param.id[1];
139         else
140             return vp->param.id;
141     }
142     return NULL;
143 }
144 
145 void
yasm_vps_delete(yasm_valparamhead * headp)146 yasm_vps_delete(yasm_valparamhead *headp)
147 {
148     yasm_valparam *cur, *next;
149 
150     cur = STAILQ_FIRST(headp);
151     while (cur) {
152         next = STAILQ_NEXT(cur, link);
153         if (cur->val)
154             yasm_xfree(cur->val);
155         switch (cur->type) {
156             case YASM_PARAM_ID:
157                 yasm_xfree(cur->param.id);
158                 break;
159             case YASM_PARAM_STRING:
160                 yasm_xfree(cur->param.str);
161                 break;
162             case YASM_PARAM_EXPR:
163                 yasm_expr_destroy(cur->param.e);
164                 break;
165         }
166         yasm_xfree(cur);
167         cur = next;
168     }
169     STAILQ_INIT(headp);
170 }
171 
172 void
yasm_vps_print(const yasm_valparamhead * headp,FILE * f)173 yasm_vps_print(const yasm_valparamhead *headp, FILE *f)
174 {
175     const yasm_valparam *vp;
176 
177     if(!headp) {
178         fprintf(f, "(none)");
179         return;
180     }
181 
182     yasm_vps_foreach(vp, headp) {
183         if (vp->val)
184             fprintf(f, "(\"%s\",", vp->val);
185         else
186             fprintf(f, "((nil),");
187         switch (vp->type) {
188             case YASM_PARAM_ID:
189                 fprintf(f, "%s", vp->param.id);
190                 break;
191             case YASM_PARAM_STRING:
192                 fprintf(f, "\"%s\"", vp->param.str);
193                 break;
194             case YASM_PARAM_EXPR:
195                 yasm_expr_print(vp->param.e, f);
196                 break;
197         }
198         fprintf(f, ")");
199         if (yasm_vps_next(vp))
200             fprintf(f, ",");
201     }
202 }
203 
204 yasm_valparamhead *
yasm_vps_create(void)205 yasm_vps_create(void)
206 {
207     yasm_valparamhead *headp = yasm_xmalloc(sizeof(yasm_valparamhead));
208     yasm_vps_initialize(headp);
209     return headp;
210 }
211 
212 void
yasm_vps_destroy(yasm_valparamhead * headp)213 yasm_vps_destroy(yasm_valparamhead *headp)
214 {
215     yasm_vps_delete(headp);
216     yasm_xfree(headp);
217 }
218 
219 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 * obj,yasm_valparam * vp,unsigned long line,void * data))220 yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
221                 const yasm_dir_help *help, size_t nhelp, void *data,
222                 int (*helper_valparam) (void *obj, yasm_valparam *vp,
223                                         unsigned long line, void *data))
224 {
225     yasm_valparam *vp = vp_first;
226     int anymatched = 0;
227     int matched;
228 
229     if (!vp)
230         return 0;
231 
232     do {
233         const char *s;
234         size_t i;
235 
236         matched = 0;
237         if (!vp->val && (s = yasm_vp_id(vp))) {
238             for (i=0; i<nhelp; i++) {
239                 if (help[i].needsparam == 0 &&
240                     yasm__strcasecmp(s, help[i].name) == 0) {
241                     if (help[i].helper(obj, vp, line,
242                                        ((char *)data)+help[i].off,
243                                        help[i].arg) != 0)
244                         return -1;
245                     matched = 1;
246                     anymatched = 1;
247                     break;
248                 }
249             }
250         } else if (vp->val) {
251             for (i=0; i<nhelp; i++) {
252                 if (help[i].needsparam == 1 &&
253                     yasm__strcasecmp(vp->val, help[i].name) == 0) {
254                     if (help[i].helper(obj, vp, line,
255                                        ((char *)data)+help[i].off,
256                                        help[i].arg) != 0)
257                         return -1;
258                     matched = 1;
259                     anymatched = 1;
260                     break;
261                 }
262             }
263         }
264 
265         if (!matched) {
266             int final = helper_valparam(obj, vp, line, data);
267             if (final < 0)
268                 return -1;
269             if (final > 0)
270                 anymatched = 1;
271         }
272     } while((vp = yasm_vps_next(vp)));
273 
274     return anymatched;
275 }
276 
277 int
yasm_dir_helper_flag_or(void * obj,yasm_valparam * vp,unsigned long line,void * d,uintptr_t flag)278 yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
279                         void *d, uintptr_t flag)
280 {
281     unsigned long *flags = (unsigned long *)d;
282     *flags |= flag;
283     return 0;
284 }
285 
286 int
yasm_dir_helper_flag_and(void * obj,yasm_valparam * vp,unsigned long line,void * d,uintptr_t flag)287 yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
288                          void *d, uintptr_t flag)
289 {
290     unsigned long *flags = (unsigned long *)d;
291     *flags &= ~flag;
292     return 0;
293 }
294 
295 int
yasm_dir_helper_flag_set(void * obj,yasm_valparam * vp,unsigned long line,void * d,uintptr_t flag)296 yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
297                          void *d, uintptr_t flag)
298 {
299     unsigned long *flags = (unsigned long *)d;
300     *flags = flag;
301     return 0;
302 }
303 
304 int
yasm_dir_helper_expr(void * obj,yasm_valparam * vp,unsigned long line,void * data,uintptr_t arg)305 yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
306                      void *data, uintptr_t arg)
307 {
308     yasm_object *object = (yasm_object *)obj;
309     yasm_expr **expr = (yasm_expr **)data;
310 
311     if (*expr)
312         yasm_expr_destroy(*expr);
313     if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) {
314         yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"),
315                        vp->val);
316         return -1;
317     }
318     return 0;
319 }
320 
321 int
yasm_dir_helper_intn(void * obj,yasm_valparam * vp,unsigned long line,void * data,uintptr_t arg)322 yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
323                      void *data, uintptr_t arg)
324 {
325     yasm_object *object = (yasm_object *)obj;
326     /*@only@*/ /*@null@*/ yasm_expr *e;
327     /*@dependent@*/ /*@null@*/ yasm_intnum *local;
328     yasm_intnum **intn = (yasm_intnum **)data;
329 
330     if (*intn)
331         yasm_intnum_destroy(*intn);
332     if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
333         !(local = yasm_expr_get_intnum(&e, 0))) {
334         yasm_error_set(YASM_ERROR_NOT_CONSTANT,
335                        N_("argument to `%s' is not an integer"),
336                        vp->val);
337         if (e)
338             yasm_expr_destroy(e);
339         return -1;
340     }
341     *intn = yasm_intnum_copy(local);
342     yasm_expr_destroy(e);
343     return 0;
344 }
345 
346 int
yasm_dir_helper_string(void * obj,yasm_valparam * vp,unsigned long line,void * data,uintptr_t arg)347 yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
348                        void *data, uintptr_t arg)
349 {
350     /*@dependent@*/ /*@null@*/ const char *local;
351     char **s = (char **)data;
352 
353     if (*s)
354         yasm_xfree(*s);
355     if (!(local = yasm_vp_string(vp))) {
356         yasm_error_set(YASM_ERROR_VALUE,
357                        N_("argument to `%s' is not a string or identifier"),
358                        vp->val);
359         return -1;
360     }
361     *s = yasm__xstrdup(local);
362     return 0;
363 }
364 
365 int
yasm_dir_helper_valparam_warn(void * obj,yasm_valparam * vp,unsigned long line,void * data)366 yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
367                               unsigned long line, void *data)
368 {
369     const char *s;
370 
371     if (vp->val) {
372         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
373                       vp->val);
374         return 0;
375     }
376 
377     if ((s = yasm_vp_id(vp)))
378         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s);
379     else if (vp->type == YASM_PARAM_STRING)
380         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier"));
381     else
382         yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier"));
383 
384     return 0;
385 }
386