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