error.c 5.0 KB

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