pragma.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2018 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * Parse and handle [pragma] directives. The preprocessor handles
  35. * %pragma preproc directives separately, all other namespaces are
  36. * simply converted to [pragma].
  37. */
  38. #include "compiler.h"
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include <limits.h>
  43. #include "nasm.h"
  44. #include "nasmlib.h"
  45. #include "assemble.h"
  46. #include "error.h"
  47. static enum directive_result output_pragma(const struct pragma *pragma);
  48. static enum directive_result limit_pragma(const struct pragma *pragma);
  49. /*
  50. * Handle [pragma] directives. [pragma] is generally produced by
  51. * the %pragma preprocessor directive, which simply passes on any
  52. * string that it finds *except* %pragma preproc. The idea is
  53. * that pragmas are of the form:
  54. *
  55. * %pragma <facility> <opname> [<options>...]
  56. *
  57. * ... where "facility" can be either a generic facility or a backend
  58. * name.
  59. *
  60. * The following names are currently reserved for global facilities;
  61. * so far none of these have any defined pragmas at all:
  62. *
  63. * preproc - preprocessor
  64. * limit - limit setting
  65. * asm - assembler
  66. * list - listing generator
  67. * file - generic file handling
  68. * input - input file handling
  69. * output - backend-independent output handling
  70. * debug - backend-independent debug handling
  71. * ignore - dummy pragma (can be used to "comment out")
  72. *
  73. * This function should generally not error out if it doesn't understand
  74. * what a pragma is for, for unknown arguments, etc; the whole point of
  75. * a pragma is that future releases might add new ones that should be
  76. * ignored rather than be an error. Erroring out is acceptable for
  77. * known pragmas suffering from parsing errors and so on.
  78. *
  79. * Adding default-suppressed warnings would, however, be a good idea
  80. * at some point.
  81. */
  82. static struct pragma_facility global_pragmas[] =
  83. {
  84. { "asm", NULL },
  85. { "limit", limit_pragma },
  86. { "list", NULL },
  87. { "file", NULL },
  88. { "input", NULL },
  89. /* None of these should actually happen due to special handling */
  90. { "preproc", NULL }, /* Handled in the preprocessor by necessity */
  91. { "output", NULL },
  92. { "debug", NULL },
  93. { "ignore", NULL },
  94. { NULL, NULL }
  95. };
  96. /*
  97. * Search a pragma list for a known pragma facility and if so, invoke
  98. * the handler. Return true if processing is complete.
  99. * The "default name", if set, matches the final NULL entry (used
  100. * for backends, so multiple backends can share the same list under
  101. * some circumstances.)
  102. */
  103. static bool search_pragma_list(const struct pragma_facility *list,
  104. const char *default_name,
  105. pragma_handler generic_handler,
  106. struct pragma *pragma)
  107. {
  108. const struct pragma_facility *pf;
  109. enum directive_result rv;
  110. if (!list)
  111. return false;
  112. for (pf = list; pf->name; pf++) {
  113. if (!nasm_stricmp(pragma->facility_name, pf->name))
  114. goto found_it;
  115. }
  116. if (default_name && !nasm_stricmp(pragma->facility_name, default_name))
  117. goto found_it;
  118. return false;
  119. found_it:
  120. pragma->facility = pf;
  121. /* If the handler is NULL all pragmas are unknown... */
  122. if (pf->handler)
  123. rv = pf->handler(pragma);
  124. else
  125. rv = DIRR_UNKNOWN;
  126. /* Is there an additional, applicable generic handler? */
  127. if (rv == DIRR_UNKNOWN && generic_handler)
  128. rv = generic_handler(pragma);
  129. switch (rv) {
  130. case DIRR_UNKNOWN:
  131. switch (pragma->opcode) {
  132. case D_none:
  133. nasm_error(ERR_WARNING|ERR_PASS2|WARN_BAD_PRAGMA,
  134. "empty %%pragma %s", pragma->facility_name);
  135. break;
  136. default:
  137. nasm_error(ERR_WARNING|ERR_PASS2|WARN_UNKNOWN_PRAGMA,
  138. "unknown %%pragma %s %s",
  139. pragma->facility_name, pragma->opname);
  140. break;
  141. }
  142. break;
  143. case DIRR_OK:
  144. case DIRR_ERROR:
  145. break; /* Nothing to do */
  146. case DIRR_BADPARAM:
  147. /*
  148. * This one is an error. Don't use it if forward compatibility
  149. * would be compromised, as opposed to an inherent error.
  150. */
  151. nasm_error(ERR_NONFATAL, "bad argument to %%pragma %s %s",
  152. pragma->facility_name, pragma->opname);
  153. break;
  154. default:
  155. panic();
  156. }
  157. return true;
  158. }
  159. void process_pragma(char *str)
  160. {
  161. struct pragma pragma;
  162. char *p;
  163. nasm_zero(pragma);
  164. pragma.facility_name = nasm_get_word(str, &p);
  165. if (!pragma.facility_name) {
  166. nasm_error(ERR_WARNING|ERR_PASS2|WARN_BAD_PRAGMA,
  167. "empty pragma directive");
  168. return; /* Empty pragma */
  169. }
  170. /*
  171. * The facility "ignore" means just that; don't even complain of
  172. * the absence of an operation.
  173. */
  174. if (!nasm_stricmp(pragma.facility_name, "ignore"))
  175. return;
  176. /*
  177. * The "output" and "debug" facilities are aliases for the
  178. * current output and debug formats, respectively.
  179. */
  180. if (!nasm_stricmp(pragma.facility_name, "output"))
  181. pragma.facility_name = ofmt->shortname;
  182. if (!nasm_stricmp(pragma.facility_name, "debug"))
  183. pragma.facility_name = dfmt->shortname;
  184. pragma.opname = nasm_get_word(p, &p);
  185. if (!pragma.opname)
  186. pragma.opcode = D_none;
  187. else
  188. pragma.opcode = directive_find(pragma.opname);
  189. pragma.tail = nasm_trim_spaces(p);
  190. /* Look for a global pragma namespace */
  191. if (search_pragma_list(global_pragmas, NULL, NULL, &pragma))
  192. return;
  193. /* Look to see if it is an output backend pragma */
  194. if (search_pragma_list(ofmt->pragmas, ofmt->shortname,
  195. output_pragma, &pragma))
  196. return;
  197. /* Look to see if it is a debug format pragma */
  198. if (search_pragma_list(dfmt->pragmas, dfmt->shortname, NULL, &pragma))
  199. return;
  200. /*
  201. * Note: it would be nice to warn for an unknown namespace,
  202. * but in order to do so we need to walk *ALL* the backends
  203. * in order to make sure we aren't dealing with a pragma that
  204. * is for another backend. On the other hand, that could
  205. * also be a warning with a separate warning flag.
  206. *
  207. * Leave this for the future, however, the warning classes are
  208. * already defined for future compatibility.
  209. */
  210. }
  211. /*
  212. * Generic pragmas that apply to all output backends; these are handled
  213. * specially so they can be made selective based on the output format.
  214. */
  215. static enum directive_result output_pragma(const struct pragma *pragma)
  216. {
  217. switch (pragma->opcode) {
  218. case D_PREFIX:
  219. case D_GPREFIX:
  220. set_label_mangle(LM_GPREFIX, pragma->tail);
  221. return DIRR_OK;
  222. case D_SUFFIX:
  223. case D_GSUFFIX:
  224. set_label_mangle(LM_GSUFFIX, pragma->tail);
  225. return DIRR_OK;
  226. case D_LPREFIX:
  227. set_label_mangle(LM_LPREFIX, pragma->tail);
  228. return DIRR_OK;
  229. case D_LSUFFIX:
  230. set_label_mangle(LM_LSUFFIX, pragma->tail);
  231. return DIRR_OK;
  232. default:
  233. return DIRR_UNKNOWN;
  234. }
  235. }
  236. /*
  237. * %pragma limit to set resource limits
  238. */
  239. static enum directive_result limit_pragma(const struct pragma *pragma)
  240. {
  241. return nasm_set_limit(pragma->opname, pragma->tail);
  242. }