valparam.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  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. #include "libyasm-stdint.h"
  29. #include "coretype.h"
  30. #include "valparam.h"
  31. #include "errwarn.h"
  32. #include "intnum.h"
  33. #include "expr.h"
  34. #include "symrec.h"
  35. #include "section.h"
  36. void
  37. yasm_call_directive(const yasm_directive *directive, yasm_object *object,
  38. yasm_valparamhead *valparams,
  39. yasm_valparamhead *objext_valparams, unsigned long line)
  40. {
  41. yasm_valparam *vp;
  42. if ((directive->flags & (YASM_DIR_ARG_REQUIRED|YASM_DIR_ID_REQUIRED)) &&
  43. (!valparams || !yasm_vps_first(valparams))) {
  44. yasm_error_set(YASM_ERROR_SYNTAX,
  45. N_("directive `%s' requires an argument"),
  46. directive->name);
  47. return;
  48. }
  49. if (valparams) {
  50. vp = yasm_vps_first(valparams);
  51. if ((directive->flags & YASM_DIR_ID_REQUIRED) &&
  52. vp->type != YASM_PARAM_ID) {
  53. yasm_error_set(YASM_ERROR_SYNTAX,
  54. N_("directive `%s' requires an identifier parameter"),
  55. directive->name);
  56. return;
  57. }
  58. }
  59. directive->handler(object, valparams, objext_valparams, line);
  60. }
  61. yasm_valparam *
  62. yasm_vp_create_id(/*@keep@*/ char *v, /*@keep@*/ char *p, int id_prefix)
  63. {
  64. yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
  65. r->val = v;
  66. r->type = YASM_PARAM_ID;
  67. r->param.id = p;
  68. r->id_prefix = (char)id_prefix;
  69. return r;
  70. }
  71. yasm_valparam *
  72. yasm_vp_create_string(/*@keep@*/ char *v, /*@keep@*/ char *p)
  73. {
  74. yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
  75. r->val = v;
  76. r->type = YASM_PARAM_STRING;
  77. r->param.str = p;
  78. r->id_prefix = '\0';
  79. return r;
  80. }
  81. yasm_valparam *
  82. yasm_vp_create_expr(/*@keep@*/ char *v, /*@keep@*/ yasm_expr *p)
  83. {
  84. yasm_valparam *r = yasm_xmalloc(sizeof(yasm_valparam));
  85. r->val = v;
  86. r->type = YASM_PARAM_EXPR;
  87. r->param.e = p;
  88. r->id_prefix = '\0';
  89. return r;
  90. }
  91. /*@null@*/ /*@only@*/ yasm_expr *
  92. yasm_vp_expr(const yasm_valparam *vp, yasm_symtab *symtab, unsigned long line)
  93. {
  94. if (!vp)
  95. return NULL;
  96. switch (vp->type) {
  97. case YASM_PARAM_ID:
  98. return yasm_expr_create_ident(yasm_expr_sym(
  99. yasm_symtab_use(symtab, yasm_vp_id(vp), line)), line);
  100. case YASM_PARAM_EXPR:
  101. return yasm_expr_copy(vp->param.e);
  102. default:
  103. return NULL;
  104. }
  105. }
  106. /*@null@*/ /*@dependent@*/ const char *
  107. yasm_vp_string(const yasm_valparam *vp)
  108. {
  109. if (!vp)
  110. return NULL;
  111. switch (vp->type) {
  112. case YASM_PARAM_ID:
  113. return vp->param.id;
  114. case YASM_PARAM_STRING:
  115. return vp->param.str;
  116. default:
  117. return NULL;
  118. }
  119. }
  120. /*@null@*/ /*@dependent@*/ const char *
  121. yasm_vp_id(const yasm_valparam *vp)
  122. {
  123. if (!vp)
  124. return NULL;
  125. if (vp->type == YASM_PARAM_ID) {
  126. if (vp->param.id[0] == vp->id_prefix)
  127. return &vp->param.id[1];
  128. else
  129. return vp->param.id;
  130. }
  131. return NULL;
  132. }
  133. void
  134. yasm_vps_delete(yasm_valparamhead *headp)
  135. {
  136. yasm_valparam *cur, *next;
  137. cur = STAILQ_FIRST(headp);
  138. while (cur) {
  139. next = STAILQ_NEXT(cur, link);
  140. if (cur->val)
  141. yasm_xfree(cur->val);
  142. switch (cur->type) {
  143. case YASM_PARAM_ID:
  144. yasm_xfree(cur->param.id);
  145. break;
  146. case YASM_PARAM_STRING:
  147. yasm_xfree(cur->param.str);
  148. break;
  149. case YASM_PARAM_EXPR:
  150. yasm_expr_destroy(cur->param.e);
  151. break;
  152. }
  153. yasm_xfree(cur);
  154. cur = next;
  155. }
  156. STAILQ_INIT(headp);
  157. }
  158. void
  159. yasm_vps_print(const yasm_valparamhead *headp, FILE *f)
  160. {
  161. const yasm_valparam *vp;
  162. if(!headp) {
  163. fprintf(f, "(none)");
  164. return;
  165. }
  166. yasm_vps_foreach(vp, headp) {
  167. if (vp->val)
  168. fprintf(f, "(\"%s\",", vp->val);
  169. else
  170. fprintf(f, "((nil),");
  171. switch (vp->type) {
  172. case YASM_PARAM_ID:
  173. fprintf(f, "%s", vp->param.id);
  174. break;
  175. case YASM_PARAM_STRING:
  176. fprintf(f, "\"%s\"", vp->param.str);
  177. break;
  178. case YASM_PARAM_EXPR:
  179. yasm_expr_print(vp->param.e, f);
  180. break;
  181. }
  182. fprintf(f, ")");
  183. if (yasm_vps_next(vp))
  184. fprintf(f, ",");
  185. }
  186. }
  187. yasm_valparamhead *
  188. yasm_vps_create(void)
  189. {
  190. yasm_valparamhead *headp = yasm_xmalloc(sizeof(yasm_valparamhead));
  191. yasm_vps_initialize(headp);
  192. return headp;
  193. }
  194. void
  195. yasm_vps_destroy(yasm_valparamhead *headp)
  196. {
  197. yasm_vps_delete(headp);
  198. yasm_xfree(headp);
  199. }
  200. int
  201. yasm_dir_helper(void *obj, yasm_valparam *vp_first, unsigned long line,
  202. const yasm_dir_help *help, size_t nhelp, void *data,
  203. int (*helper_valparam) (void *obj, yasm_valparam *vp,
  204. unsigned long line, void *data))
  205. {
  206. yasm_valparam *vp = vp_first;
  207. int anymatched = 0;
  208. int matched;
  209. if (!vp)
  210. return 0;
  211. do {
  212. const char *s;
  213. size_t i;
  214. matched = 0;
  215. if (!vp->val && (s = yasm_vp_id(vp))) {
  216. for (i=0; i<nhelp; i++) {
  217. if (help[i].needsparam == 0 &&
  218. yasm__strcasecmp(s, help[i].name) == 0) {
  219. if (help[i].helper(obj, vp, line,
  220. ((char *)data)+help[i].off,
  221. help[i].arg) != 0)
  222. return -1;
  223. matched = 1;
  224. anymatched = 1;
  225. break;
  226. }
  227. }
  228. } else if (vp->val) {
  229. for (i=0; i<nhelp; i++) {
  230. if (help[i].needsparam == 1 &&
  231. yasm__strcasecmp(vp->val, help[i].name) == 0) {
  232. if (help[i].helper(obj, vp, line,
  233. ((char *)data)+help[i].off,
  234. help[i].arg) != 0)
  235. return -1;
  236. matched = 1;
  237. anymatched = 1;
  238. break;
  239. }
  240. }
  241. }
  242. if (!matched) {
  243. int final = helper_valparam(obj, vp, line, data);
  244. if (final < 0)
  245. return -1;
  246. if (final > 0)
  247. anymatched = 1;
  248. }
  249. } while((vp = yasm_vps_next(vp)));
  250. return anymatched;
  251. }
  252. int
  253. yasm_dir_helper_flag_or(void *obj, yasm_valparam *vp, unsigned long line,
  254. void *d, uintptr_t flag)
  255. {
  256. unsigned long *flags = (unsigned long *)d;
  257. *flags |= flag;
  258. return 0;
  259. }
  260. int
  261. yasm_dir_helper_flag_and(void *obj, yasm_valparam *vp, unsigned long line,
  262. void *d, uintptr_t flag)
  263. {
  264. unsigned long *flags = (unsigned long *)d;
  265. *flags &= ~flag;
  266. return 0;
  267. }
  268. int
  269. yasm_dir_helper_flag_set(void *obj, yasm_valparam *vp, unsigned long line,
  270. void *d, uintptr_t flag)
  271. {
  272. unsigned long *flags = (unsigned long *)d;
  273. *flags = flag;
  274. return 0;
  275. }
  276. int
  277. yasm_dir_helper_expr(void *obj, yasm_valparam *vp, unsigned long line,
  278. void *data, uintptr_t arg)
  279. {
  280. yasm_object *object = (yasm_object *)obj;
  281. yasm_expr **expr = (yasm_expr **)data;
  282. if (*expr)
  283. yasm_expr_destroy(*expr);
  284. if (!(*expr = yasm_vp_expr(vp, object->symtab, line))) {
  285. yasm_error_set(YASM_ERROR_VALUE, N_("argument to `%s' is not an expression"),
  286. vp->val);
  287. return -1;
  288. }
  289. return 0;
  290. }
  291. int
  292. yasm_dir_helper_intn(void *obj, yasm_valparam *vp, unsigned long line,
  293. void *data, uintptr_t arg)
  294. {
  295. yasm_object *object = (yasm_object *)obj;
  296. /*@only@*/ /*@null@*/ yasm_expr *e;
  297. /*@dependent@*/ /*@null@*/ yasm_intnum *local;
  298. yasm_intnum **intn = (yasm_intnum **)data;
  299. if (*intn)
  300. yasm_intnum_destroy(*intn);
  301. if (!(e = yasm_vp_expr(vp, object->symtab, line)) ||
  302. !(local = yasm_expr_get_intnum(&e, 0))) {
  303. yasm_error_set(YASM_ERROR_NOT_CONSTANT,
  304. N_("argument to `%s' is not an integer"),
  305. vp->val);
  306. if (e)
  307. yasm_expr_destroy(e);
  308. return -1;
  309. }
  310. *intn = yasm_intnum_copy(local);
  311. yasm_expr_destroy(e);
  312. return 0;
  313. }
  314. int
  315. yasm_dir_helper_string(void *obj, yasm_valparam *vp, unsigned long line,
  316. void *data, uintptr_t arg)
  317. {
  318. /*@dependent@*/ /*@null@*/ const char *local;
  319. char **s = (char **)data;
  320. if (*s)
  321. yasm_xfree(*s);
  322. if (!(local = yasm_vp_string(vp))) {
  323. yasm_error_set(YASM_ERROR_VALUE,
  324. N_("argument to `%s' is not a string or identifier"),
  325. vp->val);
  326. return -1;
  327. }
  328. *s = yasm__xstrdup(local);
  329. return 0;
  330. }
  331. int
  332. yasm_dir_helper_valparam_warn(void *obj, yasm_valparam *vp,
  333. unsigned long line, void *data)
  334. {
  335. const char *s;
  336. if (vp->val) {
  337. yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"),
  338. vp->val);
  339. return 0;
  340. }
  341. if ((s = yasm_vp_id(vp)))
  342. yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized qualifier `%s'"), s);
  343. else if (vp->type == YASM_PARAM_STRING)
  344. yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized string qualifier"));
  345. else
  346. yasm_warn_set(YASM_WARN_GENERAL, N_("Unrecognized numeric qualifier"));
  347. return 0;
  348. }