error.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. /*
  2. * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
  3. * See the copyright notice in the ACK home directory, in the file "Copyright".
  4. */
  5. /* $Id$ */
  6. /* 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 */
  7. #include "lint.h"
  8. #include <varargs.h>
  9. #include <system.h>
  10. #ifndef LINT
  11. #include <em.h>
  12. #else
  13. #include "l_em.h"
  14. #endif /* LINT */
  15. #include "nopp.h"
  16. #include "errout.h"
  17. #include "debug.h"
  18. #include "tokenname.h"
  19. #include "arith.h"
  20. #include "label.h"
  21. #include "expr.h"
  22. #include "def.h"
  23. #include "LLlex.h"
  24. /* This file contains the error-message and diagnostic
  25. functions. Beware, they are called with a variable number of
  26. arguments!
  27. */
  28. /* error classes */
  29. #define WARNING 1
  30. #define ERROR 2
  31. #define CRASH 3
  32. #define FATAL 4
  33. int err_occurred = 0;
  34. extern char options[];
  35. #ifdef LINT
  36. extern char loptions[];
  37. #endif /* LINT */
  38. /* There are three general error-message functions:
  39. lexerror() lexical and pre-processor error messages
  40. error() syntactic and semantic error messages
  41. expr_error() errors in expressions
  42. The difference lies in the place where the file name and line
  43. number come from.
  44. Lexical errors report from the global variables LineNumber and
  45. FileName, expression errors get their information from the
  46. expression, whereas other errors use the information in the token.
  47. */
  48. static _error();
  49. /*VARARGS*/
  50. error(va_alist) /* fmt, args */
  51. va_dcl
  52. {
  53. va_list ap;
  54. va_start(ap);
  55. {
  56. _error(ERROR, dot.tk_file, dot.tk_line, ap);
  57. }
  58. va_end(ap);
  59. }
  60. /*VARARGS*/
  61. expr_error(va_alist) /* expr, fmt, args */
  62. va_dcl
  63. {
  64. va_list ap;
  65. va_start(ap);
  66. {
  67. register struct expr *expr = va_arg(ap, struct expr *);
  68. if (!(expr->ex_flags & EX_ERROR)) {
  69. /* to prevent proliferation */
  70. _error(ERROR, expr->ex_file, expr->ex_line, ap);
  71. expr->ex_flags |= EX_ERROR;
  72. }
  73. }
  74. va_end(ap);
  75. }
  76. /*VARARGS*/
  77. warning(va_alist) /* fmt, args */
  78. va_dcl
  79. {
  80. va_list ap;
  81. va_start(ap);
  82. {
  83. _error(WARNING, dot.tk_file, dot.tk_line, ap);
  84. }
  85. va_end(ap);
  86. }
  87. /*VARARGS*/
  88. expr_warning(va_alist) /* expr, fmt, args */
  89. va_dcl
  90. {
  91. va_list ap;
  92. va_start(ap);
  93. {
  94. struct expr *expr = va_arg(ap, struct expr *);
  95. if (!(expr->ex_flags & EX_ERROR)) {
  96. /* to prevent proliferation */
  97. _error(WARNING, expr->ex_file, expr->ex_line, ap);
  98. }
  99. }
  100. va_end(ap);
  101. }
  102. #ifdef LINT
  103. /*VARARGS*/
  104. def_warning(va_alist) /* def, fmt, args */
  105. va_dcl
  106. {
  107. va_list ap;
  108. va_start(ap);
  109. {
  110. register struct def *def = va_arg(ap, struct def *);
  111. _error(WARNING, def->df_file, def->df_line, ap);
  112. }
  113. va_end(ap);
  114. }
  115. /*VARARGS*/
  116. hwarning(va_alist) /* fmt, args */
  117. va_dcl
  118. {
  119. va_list ap;
  120. va_start(ap);
  121. {
  122. if (loptions['h'])
  123. _error(WARNING, dot.tk_file, dot.tk_line, ap);
  124. }
  125. va_end(ap);
  126. }
  127. /*VARARGS*/
  128. awarning(va_alist) /* fmt, args */
  129. va_dcl
  130. {
  131. va_list ap;
  132. va_start(ap);
  133. {
  134. if (loptions['a'])
  135. _error(WARNING, dot.tk_file, dot.tk_line, ap);
  136. }
  137. va_end(ap);
  138. }
  139. #endif /* LINT */
  140. /*VARARGS*/
  141. lexerror(va_alist) /* fmt, args */
  142. va_dcl
  143. {
  144. va_list ap;
  145. va_start(ap);
  146. {
  147. _error(ERROR, FileName, LineNumber, ap);
  148. }
  149. va_end(ap);
  150. }
  151. #ifndef NOPP
  152. /*VARARGS*/
  153. lexwarning(va_alist) /* fmt, args */
  154. va_dcl
  155. {
  156. va_list ap;
  157. va_start(ap);
  158. {
  159. _error(WARNING, FileName, LineNumber, ap);
  160. }
  161. va_end(ap);
  162. }
  163. #endif /* NOPP */
  164. /*VARARGS*/
  165. crash(va_alist) /* fmt, args */
  166. va_dcl
  167. {
  168. va_list ap;
  169. va_start(ap);
  170. {
  171. _error(CRASH, FileName, LineNumber, ap);
  172. }
  173. va_end(ap);
  174. C_close();
  175. #ifdef DEBUG
  176. sys_stop(S_ABORT);
  177. #else /* DEBUG */
  178. sys_stop(S_EXIT);
  179. #endif /* DEBUG */
  180. /* NOTREACHED */
  181. }
  182. /*VARARGS*/
  183. fatal(va_alist) /* fmt, args */
  184. va_dcl
  185. {
  186. va_list ap;
  187. va_start(ap);
  188. {
  189. _error(FATAL, FileName, LineNumber, ap);
  190. }
  191. va_end(ap);
  192. if (C_busy()) C_close();
  193. sys_stop(S_EXIT);
  194. /*NOTREACHED*/
  195. }
  196. static
  197. _error(class, fn, ln, ap)
  198. int class;
  199. char *fn;
  200. unsigned int ln;
  201. va_list ap;
  202. {
  203. char *remark;
  204. char *fmt = va_arg(ap, char *);
  205. /* check visibility of message */
  206. switch (class) {
  207. case WARNING:
  208. case ERROR:
  209. if (token_nmb < tk_nmb_at_last_syn_err + ERR_SHADOW)
  210. /* warning or error message overshadowed */
  211. return;
  212. break;
  213. }
  214. /* Since name and number are gathered from different places
  215. depending on the class, we first collect the relevant
  216. values and then decide what to print.
  217. */
  218. /* preliminaries */
  219. switch (class) {
  220. case WARNING:
  221. if (options['w'])
  222. return;
  223. break;
  224. case ERROR:
  225. case CRASH:
  226. case FATAL:
  227. if (C_busy())
  228. C_ms_err();
  229. err_occurred = 1;
  230. break;
  231. }
  232. /* the remark */
  233. switch (class) {
  234. case WARNING:
  235. #ifndef LINT
  236. remark = "(warning)";
  237. #else /* LINT */
  238. remark = 0;
  239. #endif /* LINT */
  240. break;
  241. case ERROR:
  242. remark = 0;
  243. break;
  244. case CRASH:
  245. remark = "CRASH\007";
  246. break;
  247. case FATAL:
  248. remark = "fatal error --";
  249. break;
  250. default:
  251. /*NOTREACHED*/;
  252. }
  253. #ifdef LINT
  254. if ( /* there is a file name */
  255. fn
  256. && /* the file name is global */
  257. fn[0] == '/'
  258. && /* it is not a .c file */
  259. strcmp(&fn[strlen(fn)-2], ".c") != 0
  260. ) {
  261. /* we skip this message */
  262. return;
  263. }
  264. #endif /* LINT */
  265. if (fn)
  266. fprint(ERROUT, "\"%s\", line %u: ", fn, ln);
  267. if (remark)
  268. fprint(ERROUT, "%s ", remark);
  269. doprnt(ERROUT, fmt, ap); /* contents of error */
  270. fprint(ERROUT, "\n");
  271. }