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 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 * 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 * 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 * 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 * 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 * 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 * 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 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 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 * 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 213 yasm_vps_destroy(yasm_valparamhead *headp) 214 { 215 yasm_vps_delete(headp); 216 yasm_xfree(headp); 217 } 218 219 int 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 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 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 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 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 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 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 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