errors.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. /* ------------------------------------------------------------------------- */
  2. /* "errors" : Warnings, errors and fatal errors */
  3. /* (with error throwback code for RISC OS machines) */
  4. /* */
  5. /* Part of Inform 6.33 */
  6. /* copyright (c) Graham Nelson 1993 - 2014 */
  7. /* */
  8. /* ------------------------------------------------------------------------- */
  9. #include "header.h"
  10. #define ERROR_BUFLEN (256)
  11. static char error_message_buff[ERROR_BUFLEN+4]; /* room for ellipsis */
  12. /* ------------------------------------------------------------------------- */
  13. /* Error preamble printing. */
  14. /* ------------------------------------------------------------------------- */
  15. ErrorPosition ErrorReport; /* Maintained by "lexer.c" */
  16. static void print_preamble(void)
  17. {
  18. /* Only really prints the preamble to an error or warning message:
  19. e.g. "jigsaw.apollo", line 24:
  20. The format is controllable (from an ICL switch) since this assists
  21. the working of some development environments. */
  22. int j, with_extension_flag = FALSE; char *p;
  23. j = ErrorReport.file_number;
  24. if (j <= 0 || j > input_file) p = ErrorReport.source;
  25. else p = InputFiles[j-1].filename;
  26. if (!p) p = "";
  27. switch(error_format)
  28. {
  29. case 0: /* RISC OS error message format */
  30. if (!(ErrorReport.main_flag)) printf("\"%s\", ", p);
  31. printf("line %d: ", ErrorReport.line_number);
  32. break;
  33. case 1: /* Microsoft error message format */
  34. for (j=0; p[j]!=0; j++)
  35. { if (p[j] == FN_SEP) with_extension_flag = TRUE;
  36. if (p[j] == '.') with_extension_flag = FALSE;
  37. }
  38. printf("%s", p);
  39. if (with_extension_flag) printf("%s", Source_Extension);
  40. printf("(%d): ", ErrorReport.line_number);
  41. break;
  42. case 2: /* Macintosh Programmer's Workshop error message format */
  43. printf("File \"%s\"; Line %d\t# ", p, ErrorReport.line_number);
  44. break;
  45. }
  46. }
  47. static void ellipsize_error_message_buff(void)
  48. {
  49. /* If the error buffer was actually filled up by a message, it was
  50. probably truncated too. Add an ellipsis, for which we left
  51. extra room. (Yes, yes; errors that are *exactly* 255 characters
  52. long will suffer an unnecessary ellipsis.) */
  53. if (strlen(error_message_buff) == ERROR_BUFLEN-1)
  54. strcat(error_message_buff, "...");
  55. }
  56. /* ------------------------------------------------------------------------- */
  57. /* Fatal errors (which have style 0) */
  58. /* ------------------------------------------------------------------------- */
  59. extern void fatalerror(char *s)
  60. { print_preamble();
  61. printf("Fatal error: %s\n",s);
  62. if (no_compiler_errors > 0) print_sorry_message();
  63. #ifdef ARC_THROWBACK
  64. throwback(0, s);
  65. throwback_end();
  66. #endif
  67. #ifdef MAC_FACE
  68. close_all_source();
  69. if (temporary_files_switch) remove_temp_files();
  70. abort_transcript_file();
  71. free_arrays();
  72. if (store_the_text)
  73. my_free(&all_text,"transcription text");
  74. longjmp(g_fallback, 1);
  75. #endif
  76. exit(1);
  77. }
  78. extern void fatalerror_named(char *m, char *fn)
  79. { snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\"", m, fn);
  80. ellipsize_error_message_buff();
  81. fatalerror(error_message_buff);
  82. }
  83. extern void memory_out_error(int32 size, int32 howmany, char *name)
  84. { if (howmany == 1)
  85. snprintf(error_message_buff, ERROR_BUFLEN,
  86. "Run out of memory allocating %d bytes for %s", size, name);
  87. else
  88. snprintf(error_message_buff, ERROR_BUFLEN,
  89. "Run out of memory allocating array of %dx%d bytes for %s",
  90. howmany, size, name);
  91. ellipsize_error_message_buff();
  92. fatalerror(error_message_buff);
  93. }
  94. extern void memoryerror(char *s, int32 size)
  95. {
  96. snprintf(error_message_buff, ERROR_BUFLEN,
  97. "The memory setting %s (which is %ld at present) has been \
  98. exceeded. Try running Inform again with $%s=<some-larger-number> on the \
  99. command line.",s,(long int) size,s);
  100. ellipsize_error_message_buff();
  101. fatalerror(error_message_buff);
  102. }
  103. /* ------------------------------------------------------------------------- */
  104. /* Survivable diagnostics: */
  105. /* compilation errors style 1 */
  106. /* warnings style 2 */
  107. /* linkage errors style 3 */
  108. /* compiler errors style 4 (these should never happen and */
  109. /* indicate a bug in Inform) */
  110. /* ------------------------------------------------------------------------- */
  111. static int errors[MAX_ERRORS];
  112. int no_errors, no_warnings, no_suppressed_warnings, no_link_errors,
  113. no_compiler_errors;
  114. char *forerrors_buff;
  115. int forerrors_pointer;
  116. static void message(int style, char *s)
  117. { int throw_style = style;
  118. if (hash_printed_since_newline) printf("\n");
  119. hash_printed_since_newline = FALSE;
  120. print_preamble();
  121. switch(style)
  122. { case 1: printf("Error: "); no_errors++; break;
  123. case 2: printf("Warning: "); no_warnings++; break;
  124. case 3: printf("Error: [linking '%s'] ", current_module_filename);
  125. no_link_errors++; no_errors++; throw_style=1; break;
  126. case 4: printf("*** Compiler error: ");
  127. no_compiler_errors++; throw_style=1; break;
  128. }
  129. printf(" %s\n", s);
  130. #ifdef ARC_THROWBACK
  131. throwback(throw_style, s);
  132. #endif
  133. #ifdef MAC_FACE
  134. ProcessEvents (&g_proc);
  135. if (g_proc != true)
  136. { free_arrays();
  137. if (store_the_text)
  138. my_free(&all_text,"transcription text");
  139. close_all_source ();
  140. if (temporary_files_switch) remove_temp_files();
  141. abort_transcript_file();
  142. longjmp (g_fallback, 1);
  143. }
  144. #endif
  145. if ((!concise_switch) && (forerrors_pointer > 0) && (style <= 2))
  146. { forerrors_buff[forerrors_pointer] = 0;
  147. sprintf(forerrors_buff+68," ...etc");
  148. printf("> %s\n",forerrors_buff);
  149. }
  150. }
  151. /* ------------------------------------------------------------------------- */
  152. /* Style 1: Error message routines */
  153. /* ------------------------------------------------------------------------- */
  154. extern void error(char *s)
  155. { if (no_errors == MAX_ERRORS)
  156. fatalerror("Too many errors: giving up");
  157. errors[no_errors] = no_syntax_lines;
  158. message(1,s);
  159. }
  160. extern void error_named(char *s1, char *s2)
  161. { snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
  162. ellipsize_error_message_buff();
  163. error(error_message_buff);
  164. }
  165. extern void error_numbered(char *s1, int val)
  166. {
  167. snprintf(error_message_buff, ERROR_BUFLEN,"%s %d.",s1,val);
  168. ellipsize_error_message_buff();
  169. error(error_message_buff);
  170. }
  171. extern void error_named_at(char *s1, char *s2, int32 report_line)
  172. { int i;
  173. ErrorPosition E = ErrorReport;
  174. if (report_line != -1)
  175. { ErrorReport.file_number = report_line/FILE_LINE_SCALE_FACTOR;
  176. ErrorReport.line_number = report_line%FILE_LINE_SCALE_FACTOR;
  177. ErrorReport.main_flag = (ErrorReport.file_number == 1);
  178. }
  179. snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
  180. ellipsize_error_message_buff();
  181. i = concise_switch; concise_switch = TRUE;
  182. error(error_message_buff);
  183. ErrorReport = E; concise_switch = i;
  184. }
  185. extern void no_such_label(char *lname)
  186. { error_named("No such label as",lname);
  187. }
  188. extern void ebf_error(char *s1, char *s2)
  189. { snprintf(error_message_buff, ERROR_BUFLEN, "Expected %s but found %s", s1, s2);
  190. ellipsize_error_message_buff();
  191. error(error_message_buff);
  192. }
  193. extern void char_error(char *s, int ch)
  194. { int32 uni;
  195. uni = iso_to_unicode(ch);
  196. if (character_set_unicode)
  197. snprintf(error_message_buff, ERROR_BUFLEN, "%s (unicode) $%04x", s, uni);
  198. else if (uni >= 0x100)
  199. { snprintf(error_message_buff, ERROR_BUFLEN,
  200. "%s (unicode) $%04x = (ISO %s) $%02x", s, uni,
  201. name_of_iso_set(character_set_setting), ch);
  202. }
  203. else
  204. snprintf(error_message_buff, ERROR_BUFLEN, "%s (ISO Latin1) $%02x", s, uni);
  205. /* If the character set is set to Latin-1, and the char in question
  206. is a printable Latin-1 character, we print it in the error message.
  207. This conflates the source-text charset with the terminal charset,
  208. really, but it's not a big deal. */
  209. if (((uni>=32) && (uni<127))
  210. || (((uni >= 0xa1) && (uni <= 0xff))
  211. && (character_set_setting==1) && (!character_set_unicode)))
  212. { int curlen = strlen(error_message_buff);
  213. snprintf(error_message_buff+curlen, ERROR_BUFLEN-curlen,
  214. ", i.e., '%c'", uni);
  215. }
  216. ellipsize_error_message_buff();
  217. error(error_message_buff);
  218. }
  219. extern void unicode_char_error(char *s, int32 uni)
  220. {
  221. if (uni >= 0x100)
  222. snprintf(error_message_buff, ERROR_BUFLEN, "%s (unicode) $%04x", s, uni);
  223. else
  224. snprintf(error_message_buff, ERROR_BUFLEN, "%s (ISO Latin1) $%02x", s, uni);
  225. /* See comment above. */
  226. if (((uni>=32) && (uni<127))
  227. || (((uni >= 0xa1) && (uni <= 0xff))
  228. && (character_set_setting==1) && (!character_set_unicode)))
  229. { int curlen = strlen(error_message_buff);
  230. snprintf(error_message_buff+curlen, ERROR_BUFLEN-curlen,
  231. ", i.e., '%c'", uni);
  232. }
  233. ellipsize_error_message_buff();
  234. error(error_message_buff);
  235. }
  236. /* ------------------------------------------------------------------------- */
  237. /* Style 2: Warning message routines */
  238. /* ------------------------------------------------------------------------- */
  239. extern void warning(char *s1)
  240. { if (nowarnings_switch) { no_suppressed_warnings++; return; }
  241. message(2,s1);
  242. }
  243. extern void warning_numbered(char *s1, int val)
  244. { if (nowarnings_switch) { no_suppressed_warnings++; return; }
  245. snprintf(error_message_buff, ERROR_BUFLEN,"%s %d.", s1, val);
  246. ellipsize_error_message_buff();
  247. message(2,error_message_buff);
  248. }
  249. extern void warning_named(char *s1, char *s2)
  250. {
  251. if (nowarnings_switch) { no_suppressed_warnings++; return; }
  252. snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"", s1, s2);
  253. ellipsize_error_message_buff();
  254. message(2,error_message_buff);
  255. }
  256. extern void dbnu_warning(char *type, char *name, int32 report_line)
  257. { int i;
  258. ErrorPosition E = ErrorReport;
  259. if (nowarnings_switch) { no_suppressed_warnings++; return; }
  260. if (report_line != -1)
  261. { ErrorReport.file_number = report_line/FILE_LINE_SCALE_FACTOR;
  262. ErrorReport.line_number = report_line%FILE_LINE_SCALE_FACTOR;
  263. ErrorReport.main_flag = (ErrorReport.file_number == 1);
  264. }
  265. snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\" declared but not used", type, name);
  266. ellipsize_error_message_buff();
  267. i = concise_switch; concise_switch = TRUE;
  268. message(2,error_message_buff);
  269. concise_switch = i;
  270. ErrorReport = E;
  271. }
  272. extern void uncalled_routine_warning(char *type, char *name, int32 report_line)
  273. { int i;
  274. /* This is called for functions which have been detected by the
  275. track-unused-routines module. These will often (but not always)
  276. be also caught by dbnu_warning(), which tracks symbols rather
  277. than routine addresses. */
  278. ErrorPosition E = ErrorReport;
  279. if (nowarnings_switch) { no_suppressed_warnings++; return; }
  280. if (report_line != -1)
  281. { ErrorReport.file_number = report_line/FILE_LINE_SCALE_FACTOR;
  282. ErrorReport.line_number = report_line%FILE_LINE_SCALE_FACTOR;
  283. ErrorReport.main_flag = (ErrorReport.file_number == 1);
  284. }
  285. if (OMIT_UNUSED_ROUTINES)
  286. snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\" unused and omitted", type, name);
  287. else
  288. snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\" unused (not omitted)", type, name);
  289. ellipsize_error_message_buff();
  290. i = concise_switch; concise_switch = TRUE;
  291. message(2,error_message_buff);
  292. concise_switch = i;
  293. ErrorReport = E;
  294. }
  295. extern void obsolete_warning(char *s1)
  296. { if (is_systemfile()==1) return;
  297. if (obsolete_switch || nowarnings_switch)
  298. { no_suppressed_warnings++; return; }
  299. snprintf(error_message_buff, ERROR_BUFLEN, "Obsolete usage: %s",s1);
  300. ellipsize_error_message_buff();
  301. message(2,error_message_buff);
  302. }
  303. /* ------------------------------------------------------------------------- */
  304. /* Style 3: Link error message routines */
  305. /* ------------------------------------------------------------------------- */
  306. extern void link_error(char *s)
  307. { if (no_errors==MAX_ERRORS) fatalerror("Too many errors: giving up");
  308. errors[no_errors] = no_syntax_lines;
  309. message(3,s);
  310. }
  311. extern void link_error_named(char *s1, char *s2)
  312. { snprintf(error_message_buff, ERROR_BUFLEN,"%s \"%s\"",s1,s2);
  313. ellipsize_error_message_buff();
  314. link_error(error_message_buff);
  315. }
  316. /* ------------------------------------------------------------------------- */
  317. /* Style 4: Compiler error message routines */
  318. /* ------------------------------------------------------------------------- */
  319. extern void print_sorry_message(void)
  320. { printf(
  321. "***********************************************************************\n\
  322. * 'Compiler errors' should never occur if Inform is working properly. *\n\
  323. * This is version %d.%02d of Inform, dated %20s: so *\n\
  324. * if that was more than six months ago, there may be a more recent *\n\
  325. * version available, from which the problem may have been removed. *\n\
  326. * If not, please report this fault to: graham@gnelson.demon.co.uk *\n\
  327. * and if at all possible, please include your source code, as faults *\n\
  328. * such as these are rare and often difficult to reproduce. Sorry. *\n\
  329. ***********************************************************************\n",
  330. (RELEASE_NUMBER/100)%10, RELEASE_NUMBER%100, RELEASE_DATE);
  331. }
  332. extern int compiler_error(char *s)
  333. { if (no_link_errors > 0) return FALSE;
  334. if (no_errors > 0) return FALSE;
  335. if (no_compiler_errors==MAX_ERRORS)
  336. fatalerror("Too many compiler errors: giving up");
  337. message(4,s);
  338. return TRUE;
  339. }
  340. extern int compiler_error_named(char *s1, char *s2)
  341. { if (no_link_errors > 0) return FALSE;
  342. if (no_errors > 0) return FALSE;
  343. snprintf(error_message_buff, ERROR_BUFLEN, "%s \"%s\"",s1,s2);
  344. ellipsize_error_message_buff();
  345. compiler_error(error_message_buff);
  346. return TRUE;
  347. }
  348. /* ------------------------------------------------------------------------- */
  349. /* Code for the Acorn RISC OS operating system, donated by Robin Watts, */
  350. /* to provide error throwback under the DDE environment */
  351. /* ------------------------------------------------------------------------- */
  352. #ifdef ARC_THROWBACK
  353. #define DDEUtils_ThrowbackStart 0x42587
  354. #define DDEUtils_ThrowbackSend 0x42588
  355. #define DDEUtils_ThrowbackEnd 0x42589
  356. #include "kernel.h"
  357. extern void throwback_start(void)
  358. { _kernel_swi_regs regs;
  359. if (throwback_switch)
  360. _kernel_swi(DDEUtils_ThrowbackStart, &regs, &regs);
  361. }
  362. extern void throwback_end(void)
  363. { _kernel_swi_regs regs;
  364. if (throwback_switch)
  365. _kernel_swi(DDEUtils_ThrowbackEnd, &regs, &regs);
  366. }
  367. int throwback_started = FALSE;
  368. extern void throwback(int severity, char * error)
  369. { _kernel_swi_regs regs;
  370. if (!throwback_started)
  371. { throwback_started = TRUE;
  372. throwback_start();
  373. }
  374. if (throwback_switch)
  375. { regs.r[0] = 1;
  376. if ((ErrorReport.file_number == -1)
  377. || (ErrorReport.file_number == 0))
  378. regs.r[2] = (int) (InputFiles[0].filename);
  379. else regs.r[2] = (int) (InputFiles[ErrorReport.file_number-1].filename);
  380. regs.r[3] = ErrorReport.line_number;
  381. regs.r[4] = (2-severity);
  382. regs.r[5] = (int) error;
  383. _kernel_swi(DDEUtils_ThrowbackSend, &regs, &regs);
  384. }
  385. }
  386. #endif
  387. /* ========================================================================= */
  388. /* Data structure management routines */
  389. /* ------------------------------------------------------------------------- */
  390. extern void init_errors_vars(void)
  391. { forerrors_buff = NULL;
  392. no_errors = 0; no_warnings = 0; no_suppressed_warnings = 0;
  393. no_compiler_errors = 0;
  394. }
  395. extern void errors_begin_pass(void)
  396. { ErrorReport.line_number = 0;
  397. ErrorReport.file_number = -1;
  398. ErrorReport.source = "<no text read yet>";
  399. ErrorReport.main_flag = FALSE;
  400. }
  401. extern void errors_allocate_arrays(void)
  402. { forerrors_buff = my_malloc(512, "errors buffer");
  403. }
  404. extern void errors_free_arrays(void)
  405. { my_free(&forerrors_buff, "errors buffer");
  406. }
  407. /* ========================================================================= */