listing.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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. * listing.c listing file generator for the Netwide Assembler
  35. */
  36. #include "compiler.h"
  37. #include <stdio.h>
  38. #include <stdlib.h>
  39. #include <stddef.h>
  40. #include <string.h>
  41. #include <ctype.h>
  42. #include "nasm.h"
  43. #include "nasmlib.h"
  44. #include "error.h"
  45. #include "listing.h"
  46. #define LIST_MAX_LEN 256 /* something sensible */
  47. #define LIST_INDENT 40
  48. #define LIST_HEXBIT 18
  49. typedef struct MacroInhibit MacroInhibit;
  50. static struct MacroInhibit {
  51. MacroInhibit *next;
  52. int level;
  53. int inhibiting;
  54. } *mistack;
  55. static char xdigit[] = "0123456789ABCDEF";
  56. #define HEX(a,b) (*(a)=xdigit[((b)>>4)&15],(a)[1]=xdigit[(b)&15]);
  57. static char listline[LIST_MAX_LEN];
  58. static bool listlinep;
  59. struct list_error {
  60. struct list_error *next;
  61. char str[1];
  62. };
  63. struct list_error *listerr_head, **listerr_tail;
  64. static char listdata[2 * LIST_INDENT]; /* we need less than that actually */
  65. static int32_t listoffset;
  66. static int32_t listlineno;
  67. static int32_t listp;
  68. static int suppress; /* for INCBIN & TIMES special cases */
  69. static int listlevel, listlevel_e;
  70. static FILE *listfp;
  71. static void list_emit(void)
  72. {
  73. int i;
  74. struct list_error *le, *tmp;
  75. if (listlinep || *listdata) {
  76. fprintf(listfp, "%6"PRId32" ", listlineno);
  77. if (listdata[0])
  78. fprintf(listfp, "%08"PRIX32" %-*s", listoffset, LIST_HEXBIT + 1,
  79. listdata);
  80. else
  81. fprintf(listfp, "%*s", LIST_HEXBIT + 10, "");
  82. if (listlevel_e)
  83. fprintf(listfp, "%s<%d>", (listlevel < 10 ? " " : ""),
  84. listlevel_e);
  85. else if (listlinep)
  86. fprintf(listfp, " ");
  87. if (listlinep)
  88. fprintf(listfp, " %s", listline);
  89. putc('\n', listfp);
  90. listlinep = false;
  91. listdata[0] = '\0';
  92. }
  93. list_for_each_safe(le, tmp, listerr_head) {
  94. fprintf(listfp, "%6"PRId32" ", listlineno);
  95. for (i = 0; i < LIST_HEXBIT; i++)
  96. putc('*', listfp);
  97. if (listlevel_e)
  98. fprintf(listfp, " %s<%d>", (listlevel < 10 ? " " : ""),
  99. listlevel_e);
  100. else
  101. fprintf(listfp, " ");
  102. fprintf(listfp, " %s\n", le->str);
  103. nasm_free(le);
  104. }
  105. listerr_head = NULL;
  106. listerr_tail = &listerr_head;
  107. }
  108. static void list_init(const char *fname)
  109. {
  110. if (!fname || fname[0] == '\0') {
  111. listfp = NULL;
  112. return;
  113. }
  114. listfp = nasm_open_write(fname, NF_TEXT);
  115. if (!listfp) {
  116. nasm_error(ERR_NONFATAL, "unable to open listing file `%s'",
  117. fname);
  118. return;
  119. }
  120. *listline = '\0';
  121. listlineno = 0;
  122. listerr_head = NULL;
  123. listerr_tail = &listerr_head;
  124. listp = true;
  125. listlevel = 0;
  126. suppress = 0;
  127. mistack = nasm_malloc(sizeof(MacroInhibit));
  128. mistack->next = NULL;
  129. mistack->level = 0;
  130. mistack->inhibiting = true;
  131. }
  132. static void list_cleanup(void)
  133. {
  134. if (!listp)
  135. return;
  136. while (mistack) {
  137. MacroInhibit *temp = mistack;
  138. mistack = temp->next;
  139. nasm_free(temp);
  140. }
  141. list_emit();
  142. fclose(listfp);
  143. }
  144. static void list_out(int64_t offset, char *str)
  145. {
  146. if (strlen(listdata) + strlen(str) > LIST_HEXBIT) {
  147. strcat(listdata, "-");
  148. list_emit();
  149. }
  150. if (!listdata[0])
  151. listoffset = offset;
  152. strcat(listdata, str);
  153. }
  154. static void list_address(int64_t offset, const char *brackets,
  155. int64_t addr, int size)
  156. {
  157. char q[20];
  158. char *r = q;
  159. nasm_assert(size <= 8);
  160. *r++ = brackets[0];
  161. while (size--) {
  162. HEX(r, addr);
  163. addr >>= 8;
  164. r += 2;
  165. }
  166. *r++ = brackets[1];
  167. *r = '\0';
  168. list_out(offset, q);
  169. }
  170. static void list_output(const struct out_data *data)
  171. {
  172. char q[24];
  173. uint64_t size = data->size;
  174. uint64_t offset = data->offset;
  175. const uint8_t *p = data->data;
  176. if (!listp || suppress || user_nolist)
  177. return;
  178. switch (data->type) {
  179. case OUT_ZERODATA:
  180. if (size > 16) {
  181. snprintf(q, sizeof(q), "<zero %08"PRIX64">", size);
  182. list_out(offset, q);
  183. break;
  184. } else {
  185. p = zero_buffer;
  186. }
  187. /* fall through */
  188. case OUT_RAWDATA:
  189. {
  190. if (size == 0 && !listdata[0])
  191. listoffset = data->offset;
  192. while (size--) {
  193. HEX(q, *p);
  194. q[2] = '\0';
  195. list_out(offset++, q);
  196. p++;
  197. }
  198. break;
  199. }
  200. case OUT_ADDRESS:
  201. list_address(offset, "[]", data->toffset, size);
  202. break;
  203. case OUT_SEGMENT:
  204. q[0] = '[';
  205. memset(q+1, 's', size << 1);
  206. q[(size << 1)+1] = ']';
  207. q[(size << 1)+2] = '\0';
  208. list_out(offset, q);
  209. offset += size;
  210. break;
  211. case OUT_RELADDR:
  212. list_address(offset, "()", data->toffset, size);
  213. break;
  214. case OUT_RESERVE:
  215. {
  216. snprintf(q, sizeof(q), "<res %08"PRIX64">", size);
  217. list_out(offset, q);
  218. break;
  219. }
  220. default:
  221. panic();
  222. }
  223. }
  224. static void list_line(int type, char *line)
  225. {
  226. if (!listp)
  227. return;
  228. if (user_nolist)
  229. return;
  230. if (mistack && mistack->inhibiting) {
  231. if (type == LIST_MACRO)
  232. return;
  233. else { /* pop the m i stack */
  234. MacroInhibit *temp = mistack;
  235. mistack = temp->next;
  236. nasm_free(temp);
  237. }
  238. }
  239. list_emit();
  240. listlineno = src_get_linnum();
  241. listlinep = true;
  242. strncpy(listline, line, LIST_MAX_LEN - 1);
  243. listline[LIST_MAX_LEN - 1] = '\0';
  244. listlevel_e = listlevel;
  245. }
  246. static void list_uplevel(int type)
  247. {
  248. if (!listp)
  249. return;
  250. if (type == LIST_INCBIN || type == LIST_TIMES) {
  251. suppress |= (type == LIST_INCBIN ? 1 : 2);
  252. list_out(listoffset, type == LIST_INCBIN ? "<incbin>" : "<rept>");
  253. return;
  254. }
  255. listlevel++;
  256. if (mistack && mistack->inhibiting && type == LIST_INCLUDE) {
  257. MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
  258. temp->next = mistack;
  259. temp->level = listlevel;
  260. temp->inhibiting = false;
  261. mistack = temp;
  262. } else if (type == LIST_MACRO_NOLIST) {
  263. MacroInhibit *temp = nasm_malloc(sizeof(MacroInhibit));
  264. temp->next = mistack;
  265. temp->level = listlevel;
  266. temp->inhibiting = true;
  267. mistack = temp;
  268. }
  269. }
  270. static void list_downlevel(int type)
  271. {
  272. if (!listp)
  273. return;
  274. if (type == LIST_INCBIN || type == LIST_TIMES) {
  275. suppress &= ~(type == LIST_INCBIN ? 1 : 2);
  276. return;
  277. }
  278. listlevel--;
  279. while (mistack && mistack->level > listlevel) {
  280. MacroInhibit *temp = mistack;
  281. mistack = temp->next;
  282. nasm_free(temp);
  283. }
  284. }
  285. static void list_error(int severity, const char *fmt, ...)
  286. {
  287. struct list_error *le;
  288. va_list ap;
  289. int len;
  290. if (!listfp)
  291. return;
  292. va_start(ap, fmt);
  293. len = vsnprintf(NULL, 0, fmt, ap);
  294. va_end(ap);
  295. /* sizeof(*le) already accounts for the final NULL */
  296. le = nasm_malloc(sizeof(*le) + len);
  297. va_start(ap, fmt);
  298. vsnprintf(le->str, len+1, fmt, ap);
  299. va_end(ap);
  300. le->next = NULL;
  301. *listerr_tail = le;
  302. listerr_tail = &le->next;
  303. if ((severity & ERR_MASK) >= ERR_FATAL)
  304. list_emit();
  305. }
  306. static void list_set_offset(uint64_t offset)
  307. {
  308. listoffset = offset;
  309. }
  310. static const struct lfmt nasm_list = {
  311. list_init,
  312. list_cleanup,
  313. list_output,
  314. list_line,
  315. list_uplevel,
  316. list_downlevel,
  317. list_error,
  318. list_set_offset
  319. };
  320. const struct lfmt *lfmt = &nasm_list;