error.c 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /* E R R O R A N D D I A G N O S T I C R O U T I N E S */
  2. /* This file contains the (non-portable) error-message and diagnostic
  3. giving functions. Be aware that they are called with a variable
  4. number of arguments!
  5. */
  6. #include "debug.h"
  7. #include "errout.h"
  8. #if __STDC__
  9. #include <stdarg.h>
  10. #else
  11. #include <varargs.h>
  12. #endif
  13. #include <em_arith.h>
  14. #include <em_label.h>
  15. #include <em_code.h>
  16. #include <system.h>
  17. #include "LLlex.h"
  18. #include "f_info.h"
  19. #include "input.h"
  20. #include "main.h"
  21. #include "node.h"
  22. /* error classes */
  23. #define ERROR 1
  24. #define WARNING 2
  25. #define LEXERROR 3
  26. #define LEXWARNING 4
  27. #define CRASH 5
  28. #define FATAL 6
  29. #ifdef DEBUG
  30. #define VDEBUG 7
  31. #endif
  32. int err_occurred;
  33. extern char *symbol2str();
  34. /* There are three general error-message functions:
  35. lexerror() lexical and pre-processor error messages
  36. error() syntactic and pre-processor messagese
  37. node_error() errors in nodes
  38. The difference lies in the place where the file name and line
  39. number come from.
  40. Lexical errors report from the global variables LineNumber and
  41. FileName, node errors get their information from the
  42. node, whereas other errors use the information in the token.
  43. */
  44. #if __STDC__
  45. #ifdef DEBUG
  46. /*VARARGS*/
  47. debug(char *fmt, ...)
  48. {
  49. va_list ap;
  50. va_start(ap, fmt);
  51. {
  52. _error(VDEBUG, NULLNODE, fmt, ap);
  53. }
  54. va_end(ap);
  55. }
  56. #endif /* DEBUG */
  57. /*VARARGS*/
  58. error(char *fmt, ...)
  59. {
  60. va_list ap;
  61. va_start(ap, fmt);
  62. {
  63. _error(ERROR, NULLNODE, fmt, ap);
  64. }
  65. va_end(ap);
  66. }
  67. /*VARARGS*/
  68. node_error(struct node *node, char *fmt, ...)
  69. {
  70. va_list ap;
  71. va_start(ap, fmt);
  72. {
  73. _error(ERROR, node, fmt, ap);
  74. }
  75. va_end(ap);
  76. }
  77. /*VARARGS*/
  78. warning(char *fmt, ...)
  79. {
  80. va_list ap;
  81. va_start(ap, fmt);
  82. {
  83. _error(WARNING, NULLNODE, fmt, ap);
  84. }
  85. va_end(ap);
  86. }
  87. /*VARARGS*/
  88. node_warning(struct node *node, char *fmt, ...)
  89. {
  90. va_list ap;
  91. va_start(ap, fmt);
  92. {
  93. _error(WARNING, node, fmt, ap);
  94. }
  95. va_end(ap);
  96. }
  97. /*VARARGS*/
  98. lexerror(char *fmt, ...)
  99. {
  100. va_list ap;
  101. va_start(ap, fmt);
  102. {
  103. _error(LEXERROR, NULLNODE, fmt, ap);
  104. }
  105. va_end(ap);
  106. }
  107. /*VARARGS*/
  108. lexwarning(char *fmt, ...)
  109. {
  110. va_list ap;
  111. va_start(ap, fmt);
  112. {
  113. _error(LEXWARNING, NULLNODE, fmt, ap);
  114. }
  115. va_end(ap);
  116. }
  117. /*VARARGS*/
  118. fatal(char *fmt, ...)
  119. {
  120. va_list ap;
  121. va_start(ap, fmt);
  122. {
  123. _error(FATAL, NULLNODE, fmt, ap);
  124. }
  125. va_end(ap);
  126. sys_stop(S_EXIT);
  127. }
  128. /*VARARGS*/
  129. crash(char *fmt, ...)
  130. {
  131. va_list ap;
  132. va_start(ap, fmt);
  133. {
  134. _error(CRASH, NULLNODE, fmt, ap);
  135. }
  136. va_end(ap);
  137. #ifdef DEBUG
  138. sys_stop(S_ABORT);
  139. #else
  140. sys_stop(S_EXIT);
  141. #endif
  142. }
  143. #else
  144. #ifdef DEBUG
  145. /*VARARGS*/
  146. debug(va_alist)
  147. va_dcl
  148. {
  149. va_list ap;
  150. va_start(ap);
  151. {
  152. char *fmt = va_arg(ap, char *);
  153. _error(VDEBUG, NULLNODE, fmt, ap);
  154. }
  155. va_end(ap);
  156. }
  157. #endif /* DEBUG */
  158. /*VARARGS*/
  159. error(va_alist)
  160. va_dcl
  161. {
  162. va_list ap;
  163. va_start(ap);
  164. {
  165. char *fmt = va_arg(ap, char *);
  166. _error(ERROR, NULLNODE, fmt, ap);
  167. }
  168. va_end(ap);
  169. }
  170. /*VARARGS*/
  171. node_error(va_alist)
  172. va_dcl
  173. {
  174. va_list ap;
  175. va_start(ap);
  176. {
  177. struct node *node = va_arg(ap, struct node *);
  178. char *fmt = va_arg(ap, char *);
  179. _error(ERROR, node, fmt, ap);
  180. }
  181. va_end(ap);
  182. }
  183. /*VARARGS*/
  184. warning(va_alist)
  185. va_dcl
  186. {
  187. va_list ap;
  188. va_start(ap);
  189. {
  190. char *fmt = va_arg(ap, char *);
  191. _error(WARNING, NULLNODE, fmt, ap);
  192. }
  193. va_end(ap);
  194. }
  195. /*VARARGS*/
  196. node_warning(va_alist)
  197. va_dcl
  198. {
  199. va_list ap;
  200. va_start(ap);
  201. {
  202. char *fmt = va_arg(ap, char *);
  203. struct node *node = va_arg(ap, struct node *);
  204. _error(WARNING, node, fmt, ap);
  205. }
  206. va_end(ap);
  207. }
  208. /*VARARGS*/
  209. lexerror(va_alist)
  210. va_dcl
  211. {
  212. va_list ap;
  213. va_start(ap);
  214. {
  215. char *fmt = va_arg(ap, char *);
  216. _error(LEXERROR, NULLNODE, fmt, ap);
  217. }
  218. va_end(ap);
  219. }
  220. /*VARARGS*/
  221. lexwarning(va_alist)
  222. va_dcl
  223. {
  224. va_list ap;
  225. va_start(ap);
  226. {
  227. char *fmt = va_arg(ap, char *);
  228. _error(LEXWARNING, NULLNODE, fmt, ap);
  229. }
  230. va_end(ap);
  231. }
  232. /*VARARGS*/
  233. fatal(va_alist)
  234. va_dcl
  235. {
  236. va_list ap;
  237. va_start(ap);
  238. {
  239. char *fmt = va_arg(ap, char *);
  240. _error(FATAL, NULLNODE, fmt, ap);
  241. }
  242. va_end(ap);
  243. sys_stop(S_EXIT);
  244. }
  245. /*VARARGS*/
  246. crash(va_alist)
  247. va_dcl
  248. {
  249. va_list ap;
  250. va_start(ap);
  251. {
  252. char *fmt = va_arg(ap, char *);
  253. _error(CRASH, NULLNODE, fmt, ap);
  254. }
  255. va_end(ap);
  256. #ifdef DEBUG
  257. sys_stop(S_ABORT);
  258. #else
  259. sys_stop(S_EXIT);
  260. #endif
  261. }
  262. #endif
  263. _error(class, node, fmt, ap)
  264. int class;
  265. struct node *node;
  266. char *fmt;
  267. register va_list ap;
  268. {
  269. /* _error attempts to limit the number of error messages
  270. for a given line to MAXERR_LINE.
  271. */
  272. static unsigned int last_ln = 0;
  273. unsigned int ln = 0;
  274. static char * last_fn = 0;
  275. static int e_seen = 0, w_seen = 0;
  276. register char *remark = 0;
  277. /* Since name and number are gathered from different places
  278. depending on the class, we first collect the relevant
  279. values and then decide what to print.
  280. */
  281. /* preliminaries */
  282. switch( class ) {
  283. case ERROR:
  284. case LEXERROR:
  285. case CRASH:
  286. case FATAL:
  287. if( C_busy() ) C_ms_err();
  288. err_occurred = 1;
  289. break;
  290. }
  291. /* the remark */
  292. switch( class ) {
  293. case WARNING:
  294. case LEXWARNING:
  295. if (options['w']) return;
  296. remark = "(warning)";
  297. break;
  298. case CRASH:
  299. remark = "CRASH\007";
  300. break;
  301. case FATAL:
  302. remark = "fatal error --";
  303. break;
  304. #ifdef DEBUG
  305. case VDEBUG:
  306. remark = "(debug)";
  307. break;
  308. #endif /* DEBUG */
  309. }
  310. /* the place */
  311. switch( class ) {
  312. case ERROR:
  313. case WARNING:
  314. ln = node ? node->nd_lineno : dot.tk_lineno;
  315. break;
  316. case LEXWARNING:
  317. case LEXERROR:
  318. case CRASH:
  319. case FATAL:
  320. #ifdef DEBUG
  321. case VDEBUG:
  322. #endif /* DEBUG */
  323. ln = LineNumber;
  324. break;
  325. }
  326. #ifdef DEBUG
  327. if( class != VDEBUG ) {
  328. #endif
  329. if( FileName == last_fn && ln == last_ln ) {
  330. /* we've seen this place before */
  331. if( class != WARNING && class != LEXWARNING ) {
  332. e_seen++;
  333. if( e_seen == MAXERR_LINE ) fmt = "etc ...";
  334. else if( e_seen > MAXERR_LINE )
  335. /* and too often, I'd say ! */
  336. return;
  337. }
  338. else {
  339. w_seen++;
  340. if( w_seen == MAXERR_LINE ) fmt = "etc ...";
  341. else if( w_seen > MAXERR_LINE )
  342. return;
  343. }
  344. }
  345. else {
  346. /* brand new place */
  347. last_ln = ln;
  348. last_fn = FileName;
  349. e_seen = w_seen = 0;
  350. }
  351. #ifdef DEBUG
  352. }
  353. #endif /* DEBUG */
  354. if( FileName ) fprint(ERROUT, "\"%s\", line %u: ", FileName, ln);
  355. if( remark ) fprint(ERROUT, "%s ", remark);
  356. doprnt(ERROUT, fmt, ap); /* contents of error */
  357. fprint(ERROUT, "\n");
  358. }