vsyasm.c 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424
  1. /*
  2. * Program entry point, command line parsing
  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 <ctype.h>
  29. #include <libyasm/compat-queue.h>
  30. #include <libyasm/bitvect.h>
  31. #include <libyasm.h>
  32. #ifdef HAVE_LIBGEN_H
  33. #include <libgen.h>
  34. #endif
  35. #include "frontends/yasm/yasm-options.h"
  36. #if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
  37. #include "frontends/yasm/yasm-plugin.h"
  38. #endif
  39. #include "license.c"
  40. #if defined(CMAKE_BUILD) && !defined(BUILD_SHARED_LIBS)
  41. void yasm_init_plugin(void);
  42. #endif
  43. /*@null@*/ /*@only@*/ static char *objdir_pathname = NULL;
  44. /*@null@*/ /*@only@*/ static char *global_prefix = NULL, *global_suffix = NULL;
  45. /*@null@*/ /*@only@*/ static char *listdir_pathname = NULL;
  46. /*@null@*/ /*@only@*/ static char *mapdir_pathname = NULL;
  47. /*@null@*/ /*@only@*/ static char *objext = NULL;
  48. /*@null@*/ /*@only@*/ static char *listext = NULL, *mapext = NULL;
  49. /*@null@*/ /*@only@*/ static char *machine_name = NULL;
  50. static int special_options = 0;
  51. /*@null@*/ /*@dependent@*/ static const yasm_arch_module *
  52. cur_arch_module = NULL;
  53. /*@null@*/ /*@dependent@*/ static const yasm_parser_module *
  54. cur_parser_module = NULL;
  55. /*@null@*/ /*@dependent@*/ static const yasm_preproc_module *
  56. cur_preproc_module = NULL;
  57. /*@null@*/ static char *objfmt_keyword = NULL;
  58. /*@null@*/ /*@dependent@*/ static const yasm_objfmt_module *
  59. cur_objfmt_module = NULL;
  60. /*@null@*/ /*@dependent@*/ static const yasm_dbgfmt_module *
  61. cur_dbgfmt_module = NULL;
  62. /*@null@*/ /*@dependent@*/ static const yasm_listfmt_module *
  63. cur_listfmt_module = NULL;
  64. static unsigned int force_strict = 0;
  65. static int warning_error = 0; /* warnings being treated as errors */
  66. static FILE *errfile;
  67. /*@null@*/ /*@only@*/ static char *error_filename = NULL;
  68. static enum {
  69. EWSTYLE_GNU = 0,
  70. EWSTYLE_VC
  71. } ewmsg_style = EWSTYLE_GNU;
  72. /*@null@*/ /*@dependent@*/ static FILE *open_file(const char *filename,
  73. const char *mode);
  74. static int check_errors(/*@only@*/ yasm_errwarns *errwarns,
  75. /*@only@*/ yasm_object *object,
  76. /*@only@*/ yasm_linemap *linemap,
  77. /*@only@*/ yasm_preproc *preproc,
  78. /*@only@*/ yasm_arch *arch);
  79. static void cleanup(void);
  80. static void free_input_filenames(void);
  81. /* Forward declarations: cmd line parser handlers */
  82. static int opt_special_handler(char *cmd, /*@null@*/ char *param, int extra);
  83. static int opt_arch_handler(char *cmd, /*@null@*/ char *param, int extra);
  84. static int opt_parser_handler(char *cmd, /*@null@*/ char *param, int extra);
  85. static int opt_preproc_handler(char *cmd, /*@null@*/ char *param, int extra);
  86. static int opt_objfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
  87. static int opt_dbgfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
  88. static int opt_listfmt_handler(char *cmd, /*@null@*/ char *param, int extra);
  89. static int opt_listdir_handler(char *cmd, /*@null@*/ char *param, int extra);
  90. static int opt_objdir_handler(char *cmd, /*@null@*/ char *param, int extra);
  91. static int opt_mapdir_handler(char *cmd, /*@null@*/ char *param, int extra);
  92. static int opt_listext_handler(char *cmd, /*@null@*/ char *param, int extra);
  93. static int opt_objext_handler(char *cmd, /*@null@*/ char *param, int extra);
  94. static int opt_mapext_handler(char *cmd, /*@null@*/ char *param, int extra);
  95. static int opt_machine_handler(char *cmd, /*@null@*/ char *param, int extra);
  96. static int opt_strict_handler(char *cmd, /*@null@*/ char *param, int extra);
  97. static int opt_warning_handler(char *cmd, /*@null@*/ char *param, int extra);
  98. static int opt_error_file(char *cmd, /*@null@*/ char *param, int extra);
  99. static int opt_error_stdout(char *cmd, /*@null@*/ char *param, int extra);
  100. static int opt_include_option(char *cmd, /*@null@*/ char *param, int extra);
  101. static int opt_preproc_option(char *cmd, /*@null@*/ char *param, int extra);
  102. static int opt_ewmsg_handler(char *cmd, /*@null@*/ char *param, int extra);
  103. static int opt_prefix_handler(char *cmd, /*@null@*/ char *param, int extra);
  104. static int opt_suffix_handler(char *cmd, /*@null@*/ char *param, int extra);
  105. #if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
  106. static int opt_plugin_handler(char *cmd, /*@null@*/ char *param, int extra);
  107. #endif
  108. static /*@only@*/ char *replace_extension(const char *orig, /*@null@*/
  109. const char *ext);
  110. static void print_error(const char *fmt, ...);
  111. static /*@exits@*/ void handle_yasm_int_error(const char *file,
  112. unsigned int line,
  113. const char *message);
  114. static /*@exits@*/ void handle_yasm_fatal(const char *message, va_list va);
  115. static const char *handle_yasm_gettext(const char *msgid);
  116. static void print_yasm_error(const char *filename, unsigned long line,
  117. const char *msg, /*@null@*/ const char *xref_fn,
  118. unsigned long xref_line,
  119. /*@null@*/ const char *xref_msg);
  120. static void print_yasm_warning(const char *filename, unsigned long line,
  121. const char *msg);
  122. static void apply_preproc_builtins(yasm_preproc *preproc);
  123. static void apply_preproc_standard_macros(yasm_preproc *preproc,
  124. const yasm_stdmac *stdmacs);
  125. static void apply_preproc_saved_options(yasm_preproc *preproc);
  126. static void free_preproc_saved_options(void);
  127. static void print_list_keyword_desc(const char *name, const char *keyword);
  128. /* values for special_options */
  129. #define SPECIAL_SHOW_HELP 0x01
  130. #define SPECIAL_SHOW_VERSION 0x02
  131. #define SPECIAL_SHOW_LICENSE 0x04
  132. #define SPECIAL_LISTED 0x08
  133. /* command line options */
  134. static opt_option options[] =
  135. {
  136. { 0, "version", 0, opt_special_handler, SPECIAL_SHOW_VERSION,
  137. N_("show version text"), NULL },
  138. { 0, "license", 0, opt_special_handler, SPECIAL_SHOW_LICENSE,
  139. N_("show license text"), NULL },
  140. { 'h', "help", 0, opt_special_handler, SPECIAL_SHOW_HELP,
  141. N_("show help text"), NULL },
  142. { 'a', "arch", 1, opt_arch_handler, 0,
  143. N_("select architecture (list with -a help)"), N_("arch") },
  144. { 'p', "parser", 1, opt_parser_handler, 0,
  145. N_("select parser (list with -p help)"), N_("parser") },
  146. { 'r', "preproc", 1, opt_preproc_handler, 0,
  147. N_("select preprocessor (list with -r help)"), N_("preproc") },
  148. { 'f', "oformat", 1, opt_objfmt_handler, 0,
  149. N_("select object format (list with -f help)"), N_("format") },
  150. { 'g', "dformat", 1, opt_dbgfmt_handler, 0,
  151. N_("select debugging format (list with -g help)"), N_("debug") },
  152. { 'L', "lformat", 1, opt_listfmt_handler, 0,
  153. N_("select list format (list with -L help)"), N_("list") },
  154. { 'l', "list", 1, opt_listdir_handler, 0,
  155. N_("name of list-file output directory"), N_("pathname") },
  156. { 'o', "objdir", 1, opt_objdir_handler, 0,
  157. N_("name of object-file output directory"), N_("pathname") },
  158. { 0, "mapdir", 1, opt_mapdir_handler, 0,
  159. N_("name of map-file output directory"), N_("pathname") },
  160. { 0, "listext", 1, opt_listext_handler, 0,
  161. N_("list-file extension (default `lst')"), N_("ext") },
  162. { 0, "objext", 1, opt_objext_handler, 0,
  163. N_("object-file extension (default is by object format)"), N_("ext") },
  164. { 0, "mapext", 1, opt_mapext_handler, 0,
  165. N_("map-file extension (default `map')"), N_("ext") },
  166. { 'm', "machine", 1, opt_machine_handler, 0,
  167. N_("select machine (list with -m help)"), N_("machine") },
  168. { 0, "force-strict", 0, opt_strict_handler, 0,
  169. N_("treat all sized operands as if `strict' was used"), NULL },
  170. { 'w', NULL, 0, opt_warning_handler, 1,
  171. N_("inhibits warning messages"), NULL },
  172. { 'W', NULL, 0, opt_warning_handler, 0,
  173. N_("enables/disables warning"), NULL },
  174. { 'E', NULL, 1, opt_error_file, 0,
  175. N_("redirect error messages to file"), N_("file") },
  176. { 's', NULL, 0, opt_error_stdout, 0,
  177. N_("redirect error messages to stdout"), NULL },
  178. { 'i', NULL, 1, opt_include_option, 0,
  179. N_("add include path"), N_("path") },
  180. { 'I', NULL, 1, opt_include_option, 0,
  181. N_("add include path"), N_("path") },
  182. { 'P', NULL, 1, opt_preproc_option, 0,
  183. N_("pre-include file"), N_("filename") },
  184. { 'd', NULL, 1, opt_preproc_option, 1,
  185. N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
  186. { 'D', NULL, 1, opt_preproc_option, 1,
  187. N_("pre-define a macro, optionally to value"), N_("macro[=value]") },
  188. { 'u', NULL, 1, opt_preproc_option, 2,
  189. N_("undefine a macro"), N_("macro") },
  190. { 'U', NULL, 1, opt_preproc_option, 2,
  191. N_("undefine a macro"), N_("macro") },
  192. { 'X', NULL, 1, opt_ewmsg_handler, 0,
  193. N_("select error/warning message style (`gnu' or `vc')"), N_("style") },
  194. { 0, "prefix", 1, opt_prefix_handler, 0,
  195. N_("prepend argument to name of all external symbols"), N_("prefix") },
  196. { 0, "suffix", 1, opt_suffix_handler, 0,
  197. N_("append argument to name of all external symbols"), N_("suffix") },
  198. { 0, "postfix", 1, opt_suffix_handler, 0,
  199. N_("append argument to name of all external symbols"), N_("suffix") },
  200. #if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
  201. { 'N', "plugin", 1, opt_plugin_handler, 0,
  202. N_("load plugin module"), N_("plugin") },
  203. #endif
  204. };
  205. /* version message */
  206. /*@observer@*/ static const char *version_msg[] = {
  207. PACKAGE_STRING,
  208. "Compiled on " __DATE__ ".",
  209. "Copyright (c) 2001-2010 Peter Johnson and other Yasm developers.",
  210. "Run yasm --license for licensing overview and summary."
  211. };
  212. /* help messages */
  213. /*@observer@*/ static const char *help_head = N_(
  214. "usage: vsyasm [option]* file...\n"
  215. "Options:\n");
  216. /*@observer@*/ static const char *help_tail = N_(
  217. "\n"
  218. "Files are asm sources to be assembled.\n"
  219. "\n"
  220. "Sample invocation:\n"
  221. " vsyasm -f win64 -o objdir source1.asm source2.asm\n"
  222. "\n"
  223. "All options apply to all files.\n"
  224. "\n"
  225. "Report bugs to bug-yasm@tortall.net\n");
  226. /* parsed command line storage until appropriate modules have been loaded */
  227. typedef STAILQ_HEAD(constcharparam_head, constcharparam) constcharparam_head;
  228. typedef struct constcharparam {
  229. STAILQ_ENTRY(constcharparam) link;
  230. const char *param;
  231. int id;
  232. } constcharparam;
  233. static constcharparam_head preproc_options;
  234. static constcharparam_head input_files;
  235. static int num_input_files = 0;
  236. static int
  237. do_assemble(const char *in_filename)
  238. {
  239. yasm_object *object;
  240. const char *base_filename;
  241. char *fn = NULL;
  242. char *obj_filename, *list_filename = NULL, *map_filename = NULL;
  243. /*@null@*/ FILE *obj = NULL;
  244. yasm_arch_create_error arch_error;
  245. yasm_linemap *linemap;
  246. yasm_arch *arch = NULL;
  247. yasm_preproc *preproc = NULL;
  248. yasm_errwarns *errwarns = yasm_errwarns_create();
  249. int i, matched;
  250. /* Initialize line map */
  251. linemap = yasm_linemap_create();
  252. yasm_linemap_set(linemap, in_filename, 0, 1, 1);
  253. /* determine the output filenames */
  254. /* replace (or add) extension to base filename */
  255. yasm__splitpath(in_filename, &base_filename);
  256. if (base_filename[0] != '\0')
  257. fn = replace_extension(base_filename, objext);
  258. if (!fn)
  259. {
  260. print_error(_("could not determine output filename for `%s'"),
  261. in_filename);
  262. return EXIT_FAILURE;
  263. }
  264. obj_filename = yasm__combpath(objdir_pathname, fn);
  265. yasm_xfree(fn);
  266. if (listdir_pathname) {
  267. fn = replace_extension(base_filename, listext);
  268. if (!fn)
  269. {
  270. print_error(_("could not determine list filename for `%s'"),
  271. in_filename);
  272. return EXIT_FAILURE;
  273. }
  274. list_filename = yasm__combpath(listdir_pathname, fn);
  275. yasm_xfree(fn);
  276. }
  277. if (mapdir_pathname) {
  278. fn = replace_extension(base_filename, mapext);
  279. if (!fn)
  280. {
  281. print_error(_("could not determine map filename for `%s'"),
  282. in_filename);
  283. return EXIT_FAILURE;
  284. }
  285. map_filename = yasm__combpath(mapdir_pathname, fn);
  286. yasm_xfree(fn);
  287. }
  288. /* Set up architecture using machine and parser. */
  289. if (!machine_name) {
  290. /* If we're using x86 and the default objfmt bits is 64, default the
  291. * machine to amd64. When we get more arches with multiple machines,
  292. * we should do this in a more modular fashion.
  293. */
  294. if (strcmp(cur_arch_module->keyword, "x86") == 0 &&
  295. cur_objfmt_module->default_x86_mode_bits == 64)
  296. machine_name = yasm__xstrdup("amd64");
  297. else
  298. machine_name =
  299. yasm__xstrdup(cur_arch_module->default_machine_keyword);
  300. }
  301. arch = yasm_arch_create(cur_arch_module, machine_name,
  302. cur_parser_module->keyword, &arch_error);
  303. if (!arch) {
  304. switch (arch_error) {
  305. case YASM_ARCH_CREATE_BAD_MACHINE:
  306. print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
  307. _("FATAL"), machine_name, _("machine"),
  308. _("architecture"), cur_arch_module->keyword);
  309. break;
  310. case YASM_ARCH_CREATE_BAD_PARSER:
  311. print_error(_("%s: `%s' is not a valid %s for %s `%s'"),
  312. _("FATAL"), cur_parser_module->keyword,
  313. _("parser"), _("architecture"),
  314. cur_arch_module->keyword);
  315. break;
  316. default:
  317. print_error(_("%s: unknown architecture error"), _("FATAL"));
  318. }
  319. return EXIT_FAILURE;
  320. }
  321. /* Create object */
  322. object = yasm_object_create(in_filename, obj_filename, arch,
  323. cur_objfmt_module, cur_dbgfmt_module);
  324. if (!object) {
  325. yasm_error_class eclass;
  326. unsigned long xrefline;
  327. /*@only@*/ /*@null@*/ char *estr, *xrefstr;
  328. yasm_error_fetch(&eclass, &estr, &xrefline, &xrefstr);
  329. print_error("%s: %s", _("FATAL"), estr);
  330. yasm_xfree(estr);
  331. yasm_xfree(xrefstr);
  332. return EXIT_FAILURE;
  333. }
  334. /* Get a fresh copy of objfmt_module as it may have changed. */
  335. cur_objfmt_module = ((yasm_objfmt_base *)object->objfmt)->module;
  336. /* Check to see if the requested preprocessor is in the allowed list
  337. * for the active parser.
  338. */
  339. matched = 0;
  340. for (i=0; cur_parser_module->preproc_keywords[i]; i++)
  341. if (yasm__strcasecmp(cur_parser_module->preproc_keywords[i],
  342. cur_preproc_module->keyword) == 0)
  343. matched = 1;
  344. if (!matched) {
  345. print_error(_("%s: `%s' is not a valid %s for %s `%s'"), _("FATAL"),
  346. cur_preproc_module->keyword, _("preprocessor"),
  347. _("parser"), cur_parser_module->keyword);
  348. yasm_object_destroy(object);
  349. return EXIT_FAILURE;
  350. }
  351. if (global_prefix)
  352. yasm_object_set_global_prefix(object, global_prefix);
  353. if (global_suffix)
  354. yasm_object_set_global_suffix(object, global_suffix);
  355. preproc = yasm_preproc_create(cur_preproc_module, in_filename,
  356. object->symtab, linemap, errwarns);
  357. apply_preproc_builtins(preproc);
  358. apply_preproc_standard_macros(preproc, cur_parser_module->stdmacs);
  359. apply_preproc_standard_macros(preproc, cur_objfmt_module->stdmacs);
  360. apply_preproc_saved_options(preproc);
  361. /* Get initial x86 BITS setting from object format */
  362. if (strcmp(cur_arch_module->keyword, "x86") == 0) {
  363. yasm_arch_set_var(arch, "mode_bits",
  364. cur_objfmt_module->default_x86_mode_bits);
  365. }
  366. yasm_arch_set_var(arch, "force_strict", force_strict);
  367. /* Try to enable the map file via a map NASM directive. This is
  368. * somewhat of a hack.
  369. */
  370. if (map_filename) {
  371. const yasm_directive *dir = &cur_objfmt_module->directives[0];
  372. matched = 0;
  373. for (; dir && dir->name; dir++) {
  374. if (yasm__strcasecmp(dir->name, "map") == 0 &&
  375. yasm__strcasecmp(dir->parser, "nasm") == 0) {
  376. yasm_valparamhead vps;
  377. yasm_valparam *vp;
  378. matched = 1;
  379. yasm_vps_initialize(&vps);
  380. vp = yasm_vp_create_string(NULL, yasm__xstrdup(map_filename));
  381. yasm_vps_append(&vps, vp);
  382. dir->handler(object, &vps, NULL, 0);
  383. yasm_vps_delete(&vps);
  384. }
  385. }
  386. if (!matched) {
  387. print_error(
  388. _("warning: object format `%s' does not support map files"),
  389. cur_objfmt_module->keyword);
  390. }
  391. }
  392. /* Parse! */
  393. cur_parser_module->do_parse(object, preproc, list_filename != NULL,
  394. linemap, errwarns);
  395. if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
  396. return EXIT_FAILURE;
  397. /* Finalize parse */
  398. yasm_object_finalize(object, errwarns);
  399. if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
  400. return EXIT_FAILURE;
  401. /* Optimize */
  402. yasm_object_optimize(object, errwarns);
  403. if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
  404. return EXIT_FAILURE;
  405. /* generate any debugging information */
  406. yasm_dbgfmt_generate(object, linemap, errwarns);
  407. if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
  408. return EXIT_FAILURE;
  409. /* open the object file for output (if not already opened by dbg objfmt) */
  410. if (!obj && strcmp(cur_objfmt_module->keyword, "dbg") != 0) {
  411. obj = open_file(obj_filename, "wb");
  412. if (!obj) {
  413. yasm_preproc_destroy(preproc);
  414. yasm_object_destroy(object);
  415. yasm_linemap_destroy(linemap);
  416. yasm_errwarns_destroy(errwarns);
  417. return EXIT_FAILURE;
  418. }
  419. }
  420. /* Write the object file */
  421. yasm_objfmt_output(object, obj?obj:stderr,
  422. strcmp(cur_dbgfmt_module->keyword, "null"), errwarns);
  423. /* Close object file */
  424. if (obj)
  425. fclose(obj);
  426. /* If we had an error at this point, we also need to delete the output
  427. * object file (to make sure it's not left newer than the source).
  428. */
  429. if (yasm_errwarns_num_errors(errwarns, warning_error) > 0)
  430. remove(obj_filename);
  431. if (check_errors(errwarns, object, linemap, preproc, arch) == EXIT_FAILURE)
  432. return EXIT_FAILURE;
  433. /* Open and write the list file */
  434. if (list_filename) {
  435. yasm_listfmt *cur_listfmt;
  436. FILE *list = open_file(list_filename, "wt");
  437. if (!list) {
  438. yasm_preproc_destroy(preproc);
  439. yasm_object_destroy(object);
  440. yasm_linemap_destroy(linemap);
  441. yasm_errwarns_destroy(errwarns);
  442. return EXIT_FAILURE;
  443. }
  444. /* Initialize the list format */
  445. cur_listfmt = yasm_listfmt_create(cur_listfmt_module, in_filename,
  446. obj_filename);
  447. yasm_listfmt_output(cur_listfmt, list, linemap, arch);
  448. yasm_listfmt_destroy(cur_listfmt);
  449. fclose(list);
  450. }
  451. yasm_errwarns_output_all(errwarns, linemap, warning_error,
  452. print_yasm_error, print_yasm_warning);
  453. yasm_preproc_destroy(preproc);
  454. yasm_object_destroy(object);
  455. yasm_linemap_destroy(linemap);
  456. yasm_errwarns_destroy(errwarns);
  457. yasm_xfree(obj_filename);
  458. yasm_xfree(map_filename);
  459. yasm_xfree(list_filename);
  460. return EXIT_SUCCESS;
  461. }
  462. /* main function */
  463. /*@-globstate -unrecog@*/
  464. int
  465. main(int argc, char *argv[])
  466. {
  467. size_t i;
  468. constcharparam *infile;
  469. errfile = stderr;
  470. #if defined(HAVE_SETLOCALE) && defined(HAVE_LC_MESSAGES)
  471. setlocale(LC_MESSAGES, "");
  472. #endif
  473. #if defined(LOCALEDIR)
  474. bindtextdomain(PACKAGE, LOCALEDIR);
  475. #endif
  476. textdomain(PACKAGE);
  477. /* Initialize errwarn handling */
  478. yasm_internal_error_ = handle_yasm_int_error;
  479. yasm_fatal = handle_yasm_fatal;
  480. yasm_gettext_hook = handle_yasm_gettext;
  481. yasm_errwarn_initialize();
  482. /* Initialize BitVector (needed for intnum/floatnum). */
  483. if (BitVector_Boot() != ErrCode_Ok) {
  484. print_error(_("%s: could not initialize BitVector"), _("FATAL"));
  485. return EXIT_FAILURE;
  486. }
  487. /* Initialize intnum and floatnum */
  488. yasm_intnum_initialize();
  489. yasm_floatnum_initialize();
  490. #ifdef CMAKE_BUILD
  491. /* Load standard modules */
  492. #ifdef BUILD_SHARED_LIBS
  493. if (!load_plugin("yasmstd")) {
  494. print_error(_("%s: could not load standard modules"), _("FATAL"));
  495. return EXIT_FAILURE;
  496. }
  497. #else
  498. yasm_init_plugin();
  499. #endif
  500. #endif
  501. /* Initialize parameter storage */
  502. STAILQ_INIT(&preproc_options);
  503. STAILQ_INIT(&input_files);
  504. if (parse_cmdline(argc, argv, options, NELEMS(options), print_error))
  505. return EXIT_FAILURE;
  506. switch (special_options) {
  507. case SPECIAL_SHOW_HELP:
  508. /* Does gettext calls internally */
  509. help_msg(help_head, help_tail, options, NELEMS(options));
  510. return EXIT_SUCCESS;
  511. case SPECIAL_SHOW_VERSION:
  512. for (i=0; i<NELEMS(version_msg); i++)
  513. printf("%s\n", version_msg[i]);
  514. return EXIT_SUCCESS;
  515. case SPECIAL_SHOW_LICENSE:
  516. for (i=0; i<NELEMS(license_msg); i++)
  517. printf("%s\n", license_msg[i]);
  518. return EXIT_SUCCESS;
  519. case SPECIAL_LISTED:
  520. /* Printed out earlier */
  521. return EXIT_SUCCESS;
  522. }
  523. /* Open error file if specified. */
  524. if (error_filename) {
  525. int j;
  526. errfile = open_file(error_filename, "wt");
  527. if (!errfile)
  528. return EXIT_FAILURE;
  529. /* Print command line as first line in error file. */
  530. for (j=0; j<argc; j++)
  531. fprintf(errfile, "%s%c", argv[j], (j==argc-1) ? '\n' : ' ');
  532. }
  533. /* If not already specified, default to win32 as the object format. */
  534. if (!cur_objfmt_module) {
  535. if (!objfmt_keyword)
  536. objfmt_keyword = yasm__xstrdup("win32");
  537. cur_objfmt_module = yasm_load_objfmt(objfmt_keyword);
  538. if (!cur_objfmt_module) {
  539. print_error(_("%s: could not load default %s"), _("FATAL"),
  540. _("object format"));
  541. return EXIT_FAILURE;
  542. }
  543. }
  544. /* Default to x86 as the architecture */
  545. if (!cur_arch_module) {
  546. cur_arch_module = yasm_load_arch("x86");
  547. if (!cur_arch_module) {
  548. print_error(_("%s: could not load default %s"), _("FATAL"),
  549. _("architecture"));
  550. return EXIT_FAILURE;
  551. }
  552. }
  553. /* Check for arch help */
  554. if (machine_name && strcmp(machine_name, "help") == 0) {
  555. const yasm_arch_machine *m = cur_arch_module->machines;
  556. printf(_("Available %s for %s `%s':\n"), _("machines"),
  557. _("architecture"), cur_arch_module->keyword);
  558. while (m->keyword && m->name) {
  559. print_list_keyword_desc(m->name, m->keyword);
  560. m++;
  561. }
  562. return EXIT_SUCCESS;
  563. }
  564. /* Default to NASM as the parser */
  565. if (!cur_parser_module) {
  566. cur_parser_module = yasm_load_parser("nasm");
  567. if (!cur_parser_module) {
  568. print_error(_("%s: could not load default %s"), _("FATAL"),
  569. _("parser"));
  570. cleanup();
  571. return EXIT_FAILURE;
  572. }
  573. }
  574. /* If not already specified, default to the parser's default preproc. */
  575. if (!cur_preproc_module) {
  576. cur_preproc_module =
  577. yasm_load_preproc(cur_parser_module->default_preproc_keyword);
  578. if (!cur_preproc_module) {
  579. print_error(_("%s: could not load default %s"), _("FATAL"),
  580. _("preprocessor"));
  581. cleanup();
  582. return EXIT_FAILURE;
  583. }
  584. }
  585. /* Determine input filenames. */
  586. if (STAILQ_EMPTY(&input_files)) {
  587. print_error(_("No input files specified"));
  588. return EXIT_FAILURE;
  589. }
  590. /* If list file enabled, make sure we have a list format loaded. */
  591. if (listdir_pathname) {
  592. /* If not already specified, default to nasm as the list format. */
  593. if (!cur_listfmt_module) {
  594. cur_listfmt_module = yasm_load_listfmt("nasm");
  595. if (!cur_listfmt_module) {
  596. print_error(_("%s: could not load default %s"), _("FATAL"),
  597. _("list format"));
  598. return EXIT_FAILURE;
  599. }
  600. }
  601. }
  602. /* If not already specified, default to null as the debug format. */
  603. if (!cur_dbgfmt_module) {
  604. cur_dbgfmt_module = yasm_load_dbgfmt("null");
  605. if (!cur_dbgfmt_module) {
  606. print_error(_("%s: could not load default %s"), _("FATAL"),
  607. _("debug format"));
  608. return EXIT_FAILURE;
  609. }
  610. }
  611. /* If not already specified, output to the current directory. */
  612. if (!objdir_pathname)
  613. objdir_pathname = yasm__xstrdup("./");
  614. else if ((i = yasm__createpath(objdir_pathname)) > 0 &&
  615. num_input_files > 1) {
  616. objdir_pathname[i] = '/';
  617. objdir_pathname[i+1] = '\0';
  618. }
  619. /* Create other output directories if necessary */
  620. if (listdir_pathname && (i = yasm__createpath(listdir_pathname)) > 0 &&
  621. num_input_files > 1) {
  622. listdir_pathname[i] = '/';
  623. listdir_pathname[i+1] = '\0';
  624. }
  625. if (mapdir_pathname && (i = yasm__createpath(mapdir_pathname)) > 0 &&
  626. num_input_files > 1) {
  627. mapdir_pathname[i] = '/';
  628. mapdir_pathname[i+1] = '\0';
  629. }
  630. /* If not already specified, set file extensions */
  631. if (!objext && cur_objfmt_module->extension)
  632. objext = yasm__xstrdup(cur_objfmt_module->extension);
  633. if (!listext)
  634. listext = yasm__xstrdup("lst");
  635. if (!mapext)
  636. mapext = yasm__xstrdup("map");
  637. /* Assemble each input file. Terminate on first error. */
  638. STAILQ_FOREACH(infile, &input_files, link)
  639. {
  640. if (do_assemble(infile->param) == EXIT_FAILURE) {
  641. cleanup();
  642. return EXIT_FAILURE;
  643. }
  644. }
  645. cleanup();
  646. return EXIT_SUCCESS;
  647. }
  648. /*@=globstate =unrecog@*/
  649. /* Open the object file. Returns 0 on failure. */
  650. static FILE *
  651. open_file(const char *filename, const char *mode)
  652. {
  653. FILE *f;
  654. f = fopen(filename, mode);
  655. if (!f)
  656. print_error(_("could not open file `%s'"), filename);
  657. return f;
  658. }
  659. static int
  660. check_errors(yasm_errwarns *errwarns, yasm_object *object,
  661. yasm_linemap *linemap, yasm_preproc *preproc, yasm_arch *arch)
  662. {
  663. if (yasm_errwarns_num_errors(errwarns, warning_error) > 0) {
  664. yasm_errwarns_output_all(errwarns, linemap, warning_error,
  665. print_yasm_error, print_yasm_warning);
  666. yasm_preproc_destroy(preproc);
  667. yasm_object_destroy(object);
  668. yasm_linemap_destroy(linemap);
  669. yasm_errwarns_destroy(errwarns);
  670. return EXIT_FAILURE;
  671. }
  672. return EXIT_SUCCESS;
  673. }
  674. /* Define DO_FREE to 1 to enable deallocation of all data structures.
  675. * Useful for detecting memory leaks, but slows down execution unnecessarily
  676. * (as the OS will free everything we miss here).
  677. */
  678. #define DO_FREE 1
  679. /* Cleans up all allocated structures. */
  680. static void
  681. cleanup(void)
  682. {
  683. if (DO_FREE) {
  684. yasm_floatnum_cleanup();
  685. yasm_intnum_cleanup();
  686. yasm_errwarn_cleanup();
  687. BitVector_Shutdown();
  688. }
  689. if (DO_FREE) {
  690. free_input_filenames();
  691. if (objdir_pathname)
  692. yasm_xfree(objdir_pathname);
  693. if (listdir_pathname)
  694. yasm_xfree(listdir_pathname);
  695. if (mapdir_pathname)
  696. yasm_xfree(mapdir_pathname);
  697. if (objext)
  698. yasm_xfree(objext);
  699. if (listext)
  700. yasm_xfree(listext);
  701. if (mapext)
  702. yasm_xfree(mapext);
  703. if (machine_name)
  704. yasm_xfree(machine_name);
  705. if (objfmt_keyword)
  706. yasm_xfree(objfmt_keyword);
  707. free_preproc_saved_options();
  708. }
  709. if (errfile != stderr && errfile != stdout)
  710. fclose(errfile);
  711. #if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
  712. unload_plugins();
  713. #endif
  714. }
  715. static void
  716. free_input_filenames(void)
  717. {
  718. constcharparam *cp, *cpnext;
  719. cp = STAILQ_FIRST(&input_files);
  720. while (cp != NULL) {
  721. cpnext = STAILQ_NEXT(cp, link);
  722. yasm_xfree(cp);
  723. cp = cpnext;
  724. }
  725. STAILQ_INIT(&input_files);
  726. }
  727. /*
  728. * Command line options handlers
  729. */
  730. int
  731. not_an_option_handler(char *param)
  732. {
  733. constcharparam *cp;
  734. cp = yasm_xmalloc(sizeof(constcharparam));
  735. cp->param = param;
  736. cp->id = 0;
  737. STAILQ_INSERT_TAIL(&input_files, cp, link);
  738. ++num_input_files;
  739. return 0;
  740. }
  741. int
  742. other_option_handler(char *option)
  743. {
  744. /* Accept, but ignore, -O and -Onnn, for compatibility with NASM. */
  745. if (option[0] == '-' && option[1] == 'O') {
  746. int n = 2;
  747. for (;;) {
  748. if (option[n] == '\0')
  749. return 0;
  750. if (!isdigit(option[n]))
  751. return 1;
  752. n++;
  753. }
  754. }
  755. return 1;
  756. }
  757. static int
  758. opt_special_handler(/*@unused@*/ char *cmd, /*@unused@*/ char *param, int extra)
  759. {
  760. if (special_options == 0)
  761. special_options = extra;
  762. return 0;
  763. }
  764. static int
  765. opt_arch_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  766. {
  767. assert(param != NULL);
  768. cur_arch_module = yasm_load_arch(param);
  769. if (!cur_arch_module) {
  770. if (!strcmp("help", param)) {
  771. printf(_("Available yasm %s:\n"), _("architectures"));
  772. yasm_list_arch(print_list_keyword_desc);
  773. special_options = SPECIAL_LISTED;
  774. return 0;
  775. }
  776. print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
  777. _("architecture"), param);
  778. exit(EXIT_FAILURE);
  779. }
  780. return 0;
  781. }
  782. static int
  783. opt_parser_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  784. {
  785. assert(param != NULL);
  786. cur_parser_module = yasm_load_parser(param);
  787. if (!cur_parser_module) {
  788. if (!strcmp("help", param)) {
  789. printf(_("Available yasm %s:\n"), _("parsers"));
  790. yasm_list_parser(print_list_keyword_desc);
  791. special_options = SPECIAL_LISTED;
  792. return 0;
  793. }
  794. print_error(_("%s: unrecognized %s `%s'"), _("FATAL"), _("parser"),
  795. param);
  796. exit(EXIT_FAILURE);
  797. }
  798. return 0;
  799. }
  800. static int
  801. opt_preproc_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  802. {
  803. assert(param != NULL);
  804. cur_preproc_module = yasm_load_preproc(param);
  805. if (!cur_preproc_module) {
  806. if (!strcmp("help", param)) {
  807. printf(_("Available yasm %s:\n"), _("preprocessors"));
  808. yasm_list_preproc(print_list_keyword_desc);
  809. special_options = SPECIAL_LISTED;
  810. return 0;
  811. }
  812. print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
  813. _("preprocessor"), param);
  814. exit(EXIT_FAILURE);
  815. }
  816. return 0;
  817. }
  818. static int
  819. opt_objfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  820. {
  821. size_t i;
  822. assert(param != NULL);
  823. cur_objfmt_module = yasm_load_objfmt(param);
  824. if (!cur_objfmt_module) {
  825. if (!strcmp("help", param)) {
  826. printf(_("Available yasm %s:\n"), _("object formats"));
  827. yasm_list_objfmt(print_list_keyword_desc);
  828. special_options = SPECIAL_LISTED;
  829. return 0;
  830. }
  831. print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
  832. _("object format"), param);
  833. exit(EXIT_FAILURE);
  834. }
  835. if (objfmt_keyword)
  836. yasm_xfree(objfmt_keyword);
  837. objfmt_keyword = yasm__xstrdup(param);
  838. for (i=0; i<strlen(objfmt_keyword); i++)
  839. objfmt_keyword[i] = tolower(objfmt_keyword[i]);
  840. return 0;
  841. }
  842. static int
  843. opt_dbgfmt_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  844. {
  845. assert(param != NULL);
  846. cur_dbgfmt_module = yasm_load_dbgfmt(param);
  847. if (!cur_dbgfmt_module) {
  848. if (!strcmp("help", param)) {
  849. printf(_("Available yasm %s:\n"), _("debug formats"));
  850. yasm_list_dbgfmt(print_list_keyword_desc);
  851. special_options = SPECIAL_LISTED;
  852. return 0;
  853. }
  854. print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
  855. _("debug format"), param);
  856. exit(EXIT_FAILURE);
  857. }
  858. return 0;
  859. }
  860. static int
  861. opt_listfmt_handler(/*@unused@*/ char *cmd, char *param,
  862. /*@unused@*/ int extra)
  863. {
  864. assert(param != NULL);
  865. cur_listfmt_module = yasm_load_listfmt(param);
  866. if (!cur_listfmt_module) {
  867. if (!strcmp("help", param)) {
  868. printf(_("Available yasm %s:\n"), _("list formats"));
  869. yasm_list_listfmt(print_list_keyword_desc);
  870. special_options = SPECIAL_LISTED;
  871. return 0;
  872. }
  873. print_error(_("%s: unrecognized %s `%s'"), _("FATAL"),
  874. _("list format"), param);
  875. exit(EXIT_FAILURE);
  876. }
  877. return 0;
  878. }
  879. static int
  880. opt_listdir_handler(/*@unused@*/ char *cmd, char *param,
  881. /*@unused@*/ int extra)
  882. {
  883. if (listdir_pathname) {
  884. print_error(
  885. _("warning: can output to only one list dir, last specified used"));
  886. yasm_xfree(listdir_pathname);
  887. }
  888. assert(param != NULL);
  889. listdir_pathname = yasm_xmalloc(strlen(param)+2);
  890. strcpy(listdir_pathname, param);
  891. return 0;
  892. }
  893. static int
  894. opt_objdir_handler(/*@unused@*/ char *cmd, char *param,
  895. /*@unused@*/ int extra)
  896. {
  897. if (objdir_pathname) {
  898. print_error(
  899. _("warning: can output to only one object dir, last specified used"));
  900. yasm_xfree(objdir_pathname);
  901. }
  902. assert(param != NULL);
  903. objdir_pathname = yasm_xmalloc(strlen(param)+2);
  904. strcpy(objdir_pathname, param);
  905. return 0;
  906. }
  907. static int
  908. opt_mapdir_handler(/*@unused@*/ char *cmd, char *param,
  909. /*@unused@*/ int extra)
  910. {
  911. if (mapdir_pathname) {
  912. print_error(
  913. _("warning: can output to only one map file, last specified used"));
  914. yasm_xfree(mapdir_pathname);
  915. }
  916. assert(param != NULL);
  917. mapdir_pathname = yasm_xmalloc(strlen(param)+2);
  918. strcpy(mapdir_pathname, param);
  919. return 0;
  920. }
  921. static int
  922. opt_listext_handler(/*@unused@*/ char *cmd, char *param,
  923. /*@unused@*/ int extra)
  924. {
  925. if (listext) {
  926. print_error(
  927. _("warning: can set only one list extension, last specified used"));
  928. yasm_xfree(listext);
  929. }
  930. assert(param != NULL);
  931. listext = yasm__xstrdup(param);
  932. return 0;
  933. }
  934. static int
  935. opt_objext_handler(/*@unused@*/ char *cmd, char *param,
  936. /*@unused@*/ int extra)
  937. {
  938. if (objext) {
  939. print_error(
  940. _("warning: can set only one object extension, last specified used"));
  941. yasm_xfree(objext);
  942. }
  943. assert(param != NULL);
  944. objext = yasm__xstrdup(param);
  945. return 0;
  946. }
  947. static int
  948. opt_mapext_handler(/*@unused@*/ char *cmd, char *param,
  949. /*@unused@*/ int extra)
  950. {
  951. if (mapext) {
  952. print_error(
  953. _("warning: can set only one map extension, last specified used"));
  954. yasm_xfree(mapext);
  955. }
  956. assert(param != NULL);
  957. mapext = yasm__xstrdup(param);
  958. return 0;
  959. }
  960. static int
  961. opt_machine_handler(/*@unused@*/ char *cmd, char *param,
  962. /*@unused@*/ int extra)
  963. {
  964. if (machine_name)
  965. yasm_xfree(machine_name);
  966. assert(param != NULL);
  967. machine_name = yasm__xstrdup(param);
  968. return 0;
  969. }
  970. static int
  971. opt_strict_handler(/*@unused@*/ char *cmd,
  972. /*@unused@*/ /*@null@*/ char *param,
  973. /*@unused@*/ int extra)
  974. {
  975. force_strict = 1;
  976. return 0;
  977. }
  978. static int
  979. opt_warning_handler(char *cmd, /*@unused@*/ char *param, int extra)
  980. {
  981. /* is it disabling the warning instead of enabling? */
  982. void (*action)(yasm_warn_class wclass) = yasm_warn_enable;
  983. if (extra == 1) {
  984. /* -w, disable warnings */
  985. yasm_warn_disable_all();
  986. return 0;
  987. }
  988. /* skip past 'W' */
  989. cmd++;
  990. /* detect no- prefix to disable the warning */
  991. if (cmd[0] == 'n' && cmd[1] == 'o' && cmd[2] == '-') {
  992. action = yasm_warn_disable;
  993. cmd += 3; /* skip past it to get to the warning name */
  994. }
  995. if (cmd[0] == '\0')
  996. /* just -W or -Wno-, so definitely not valid */
  997. return 1;
  998. else if (strcmp(cmd, "error") == 0)
  999. warning_error = (action == yasm_warn_enable);
  1000. else if (strcmp(cmd, "unrecognized-char") == 0)
  1001. action(YASM_WARN_UNREC_CHAR);
  1002. else if (strcmp(cmd, "orphan-labels") == 0)
  1003. action(YASM_WARN_ORPHAN_LABEL);
  1004. else if (strcmp(cmd, "uninit-contents") == 0)
  1005. action(YASM_WARN_UNINIT_CONTENTS);
  1006. else if (strcmp(cmd, "size-override") == 0)
  1007. action(YASM_WARN_SIZE_OVERRIDE);
  1008. else
  1009. return 1;
  1010. return 0;
  1011. }
  1012. static int
  1013. opt_error_file(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  1014. {
  1015. if (error_filename) {
  1016. print_error(
  1017. _("warning: can output to only one error file, last specified used"));
  1018. yasm_xfree(error_filename);
  1019. }
  1020. assert(param != NULL);
  1021. error_filename = yasm__xstrdup(param);
  1022. return 0;
  1023. }
  1024. static int
  1025. opt_error_stdout(/*@unused@*/ char *cmd, /*@unused@*/ char *param,
  1026. /*@unused@*/ int extra)
  1027. {
  1028. /* Clear any specified error filename */
  1029. if (error_filename) {
  1030. yasm_xfree(error_filename);
  1031. error_filename = NULL;
  1032. }
  1033. errfile = stdout;
  1034. return 0;
  1035. }
  1036. static int
  1037. opt_include_option(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  1038. {
  1039. yasm_add_include_path(param);
  1040. return 0;
  1041. }
  1042. static int
  1043. opt_preproc_option(/*@unused@*/ char *cmd, char *param, int extra)
  1044. {
  1045. constcharparam *cp;
  1046. cp = yasm_xmalloc(sizeof(constcharparam));
  1047. cp->param = param;
  1048. cp->id = extra;
  1049. STAILQ_INSERT_TAIL(&preproc_options, cp, link);
  1050. return 0;
  1051. }
  1052. static int
  1053. opt_ewmsg_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  1054. {
  1055. if (yasm__strcasecmp(param, "gnu") == 0 ||
  1056. yasm__strcasecmp(param, "gcc") == 0) {
  1057. ewmsg_style = EWSTYLE_GNU;
  1058. } else if (yasm__strcasecmp(param, "vc") == 0) {
  1059. ewmsg_style = EWSTYLE_VC;
  1060. } else
  1061. print_error(_("warning: unrecognized message style `%s'"), param);
  1062. return 0;
  1063. }
  1064. static int
  1065. opt_prefix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  1066. {
  1067. if (global_prefix)
  1068. yasm_xfree(global_prefix);
  1069. assert(param != NULL);
  1070. global_prefix = yasm__xstrdup(param);
  1071. return 0;
  1072. }
  1073. static int
  1074. opt_suffix_handler(/*@unused@*/ char *cmd, char *param, /*@unused@*/ int extra)
  1075. {
  1076. if (global_suffix)
  1077. yasm_xfree(global_suffix);
  1078. assert(param != NULL);
  1079. global_suffix = yasm__xstrdup(param);
  1080. return 0;
  1081. }
  1082. #if defined(CMAKE_BUILD) && defined(BUILD_SHARED_LIBS)
  1083. static int
  1084. opt_plugin_handler(/*@unused@*/ char *cmd, char *param,
  1085. /*@unused@*/ int extra)
  1086. {
  1087. if (!load_plugin(param))
  1088. print_error(_("warning: could not load plugin `%s'"), param);
  1089. return 0;
  1090. }
  1091. #endif
  1092. static void
  1093. apply_preproc_builtins(yasm_preproc *preproc)
  1094. {
  1095. char *predef;
  1096. /* Define standard YASM assembly-time macro constants */
  1097. predef = yasm_xmalloc(strlen("__YASM_OBJFMT__=")
  1098. + strlen(objfmt_keyword) + 1);
  1099. strcpy(predef, "__YASM_OBJFMT__=");
  1100. strcat(predef, objfmt_keyword);
  1101. yasm_preproc_define_builtin(preproc, predef);
  1102. yasm_xfree(predef);
  1103. }
  1104. static void
  1105. apply_preproc_standard_macros(yasm_preproc *preproc, const yasm_stdmac *stdmacs)
  1106. {
  1107. int i, matched;
  1108. if (!stdmacs)
  1109. return;
  1110. matched = -1;
  1111. for (i=0; stdmacs[i].parser; i++)
  1112. if (yasm__strcasecmp(stdmacs[i].parser,
  1113. cur_parser_module->keyword) == 0 &&
  1114. yasm__strcasecmp(stdmacs[i].preproc,
  1115. cur_preproc_module->keyword) == 0)
  1116. matched = i;
  1117. if (matched >= 0 && stdmacs[matched].macros)
  1118. yasm_preproc_add_standard(preproc, stdmacs[matched].macros);
  1119. }
  1120. static void
  1121. apply_preproc_saved_options(yasm_preproc *preproc)
  1122. {
  1123. constcharparam *cp;
  1124. void (*funcs[3])(yasm_preproc *, const char *);
  1125. funcs[0] = cur_preproc_module->add_include_file;
  1126. funcs[1] = cur_preproc_module->predefine_macro;
  1127. funcs[2] = cur_preproc_module->undefine_macro;
  1128. STAILQ_FOREACH(cp, &preproc_options, link) {
  1129. if (0 <= cp->id && cp->id < 3 && funcs[cp->id])
  1130. funcs[cp->id](preproc, cp->param);
  1131. }
  1132. }
  1133. static void
  1134. free_preproc_saved_options(void)
  1135. {
  1136. constcharparam *cp, *cpnext;
  1137. cp = STAILQ_FIRST(&preproc_options);
  1138. while (cp != NULL) {
  1139. cpnext = STAILQ_NEXT(cp, link);
  1140. yasm_xfree(cp);
  1141. cp = cpnext;
  1142. }
  1143. STAILQ_INIT(&preproc_options);
  1144. }
  1145. /* Replace extension on a filename (or append one if none is present).
  1146. * If output filename would be identical to input (same extension out as in),
  1147. * returns NULL.
  1148. * A NULL ext means the trailing '.' should NOT be included, whereas a "" ext
  1149. * means the trailing '.' should be included.
  1150. */
  1151. static char *
  1152. replace_extension(const char *orig, /*@null@*/ const char *ext)
  1153. {
  1154. char *out, *outext;
  1155. size_t outlen;
  1156. /* allocate enough space for full existing name + extension */
  1157. outlen = strlen(orig) + 2;
  1158. if (ext)
  1159. outlen += strlen(ext) + 1;
  1160. out = yasm_xmalloc(outlen);
  1161. strcpy(out, orig);
  1162. outext = strrchr(out, '.');
  1163. if (outext) {
  1164. /* Existing extension: make sure it's not the same as the replacement
  1165. * (as we don't want to overwrite the source file).
  1166. */
  1167. outext++; /* advance past '.' */
  1168. if (ext && strcmp(outext, ext) == 0) {
  1169. outext = NULL; /* indicate default should be used */
  1170. print_error(_("file name already ends in `.%s'"), ext);
  1171. }
  1172. } else {
  1173. /* No extension: make sure the output extension is not empty
  1174. * (again, we don't want to overwrite the source file).
  1175. */
  1176. if (!ext) {
  1177. outext = NULL;
  1178. print_error(_("file name already has no extension"));
  1179. } else {
  1180. outext = strrchr(out, '\0'); /* point to end of the string */
  1181. *outext++ = '.'; /* append '.' */
  1182. }
  1183. }
  1184. /* replace extension or use default name */
  1185. if (outext) {
  1186. if (!ext) {
  1187. /* Back up and replace '.' with string terminator */
  1188. outext--;
  1189. *outext = '\0';
  1190. } else
  1191. strcpy(outext, ext);
  1192. } else
  1193. return NULL;
  1194. return out;
  1195. }
  1196. void
  1197. print_list_keyword_desc(const char *name, const char *keyword)
  1198. {
  1199. printf("%4s%-12s%s\n", "", keyword, name);
  1200. }
  1201. static void
  1202. print_error(const char *fmt, ...)
  1203. {
  1204. va_list va;
  1205. fprintf(errfile, "vsyasm: ");
  1206. va_start(va, fmt);
  1207. vfprintf(errfile, fmt, va);
  1208. va_end(va);
  1209. fputc('\n', errfile);
  1210. }
  1211. static /*@exits@*/ void
  1212. handle_yasm_int_error(const char *file, unsigned int line, const char *message)
  1213. {
  1214. fprintf(stderr, _("INTERNAL ERROR at %s, line %u: %s\n"), file, line,
  1215. gettext(message));
  1216. #ifdef HAVE_ABORT
  1217. abort();
  1218. #else
  1219. exit(EXIT_FAILURE);
  1220. #endif
  1221. }
  1222. static /*@exits@*/ void
  1223. handle_yasm_fatal(const char *fmt, va_list va)
  1224. {
  1225. fprintf(errfile, "vsyasm: %s: ", _("FATAL"));
  1226. vfprintf(errfile, gettext(fmt), va);
  1227. fputc('\n', errfile);
  1228. exit(EXIT_FAILURE);
  1229. }
  1230. static const char *
  1231. handle_yasm_gettext(const char *msgid)
  1232. {
  1233. return gettext(msgid);
  1234. }
  1235. static const char *fmt[2] = {
  1236. "%s:%lu: %s%s\n", /* GNU */
  1237. "%s(%lu) : %s%s\n" /* VC */
  1238. };
  1239. static const char *fmt_noline[2] = {
  1240. "%s: %s%s\n", /* GNU */
  1241. "%s : %s%s\n" /* VC */
  1242. };
  1243. static void
  1244. print_yasm_error(const char *filename, unsigned long line, const char *msg,
  1245. const char *xref_fn, unsigned long xref_line,
  1246. const char *xref_msg)
  1247. {
  1248. if (line)
  1249. fprintf(errfile, fmt[ewmsg_style], filename, line, _("error: "), msg);
  1250. else
  1251. fprintf(errfile, fmt_noline[ewmsg_style], filename, _("error: "), msg);
  1252. if (xref_fn && xref_msg) {
  1253. if (xref_line)
  1254. fprintf(errfile, fmt[ewmsg_style], xref_fn, xref_line, _("error: "),
  1255. xref_msg);
  1256. else
  1257. fprintf(errfile, fmt_noline[ewmsg_style], xref_fn, _("error: "),
  1258. xref_msg);
  1259. }
  1260. }
  1261. static void
  1262. print_yasm_warning(const char *filename, unsigned long line, const char *msg)
  1263. {
  1264. if (line)
  1265. fprintf(errfile, fmt[ewmsg_style], filename, line, _("warning: "),
  1266. msg);
  1267. else
  1268. fprintf(errfile, fmt_noline[ewmsg_style], filename, _("warning: "),
  1269. msg);
  1270. }