log.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. /*
  2. The logging machine
  3. */
  4. /* $Id$ */
  5. #include <stdio.h>
  6. #if __STDC__
  7. #include <stdarg.h>
  8. #else
  9. #include <varargs.h>
  10. #endif
  11. #include "logging.h"
  12. #include "global.h"
  13. #include "linfil.h"
  14. #ifdef LOGGING
  15. extern int strlen();
  16. extern char *strcpy();
  17. extern long mess_id; /* from io.c */
  18. extern FILE *fcreat_high(); /* from io.c */
  19. /******** The Logging Machine Variables ********/
  20. extern long atol();
  21. long inr; /* current instruction number */
  22. int must_log; /* set if logging may be required */
  23. long log_start; /* first instruction to be logged */
  24. int logging; /* set as soon as logging starts */
  25. PRIVATE long stop; /* inr after which to stop */
  26. PRIVATE long gdump; /* inr at which to dump GDA */
  27. PRIVATE ptr gmin, gmax; /* GDA dump limits */
  28. PRIVATE long hdump; /* inr at which to dump the heap */
  29. PRIVATE long stdsize; /* optional size of stack dump */
  30. PRIVATE int stdrawflag; /* set if unformatted stack dump */
  31. PRIVATE char log_file[64] = "int.log"; /* Name of log file */
  32. PRIVATE long at; /* patch to set log_start */
  33. PRIVATE char *lmask; /* patch to set logmask */
  34. PRIVATE char *logvar; /* Name of LOG variable */
  35. PRIVATE int log_level[128]; /* Holds the log levels */
  36. PRIVATE FILE *log_fp; /* Filepointer of log file */
  37. /* arguments for the logging machine */
  38. PRIVATE int argcount;
  39. PRIVATE char *arglist[20]; /* arbitrary size */
  40. PRIVATE char *getpar();
  41. PRIVATE long longpar();
  42. PRIVATE set_lmask();
  43. int logarg(str)
  44. char *str;
  45. {
  46. /* If the string might be an interesting argument for the
  47. logging machine, it is stored in the arglist, and logarg
  48. succeeds. Otherwise it fails.
  49. The string is interesting if it contains a '='.
  50. */
  51. register char *arg = str;
  52. register char ch;
  53. while ((ch = *arg) && (ch != '=')) {
  54. arg++;
  55. }
  56. if (ch == '=') {
  57. if (argcount == (sizeof arglist /sizeof arglist[0]))
  58. fatal("too many logging arguments on command line");
  59. arglist[argcount++] = str;
  60. return 1;
  61. }
  62. return 0;
  63. }
  64. init_log()
  65. {
  66. /* setting the logging machine */
  67. stop = longpar("STOP", 0L);
  68. gdump = longpar("GDA", 0L);
  69. if (gdump) {
  70. gmin = i2p(longpar("GMIN", 0L));
  71. gmax = i2p(longpar("GMAX", 0L));
  72. set_lmask("+1");
  73. }
  74. hdump = longpar("HEAP", 0L);
  75. if (hdump) {
  76. set_lmask("*1");
  77. }
  78. stdsize = longpar("STDSIZE", 0L);
  79. stdrawflag = longpar("RAWSTACK", 0L);
  80. if (getpar("LOGFILE")) {
  81. strcpy(log_file, getpar("LOGFILE"));
  82. }
  83. if ((at = longpar("AT", 0L))) {
  84. /* abbreviation for: */
  85. stop = at + 1; /* stop AFTER at + 1 */
  86. /* Note: the setting of log_start is deferred to
  87. init_ofiles(1), for implementation reasons. The
  88. AT-variable presently only works for the top
  89. level.
  90. */
  91. }
  92. if ((lmask = getpar("L"))) {
  93. /* abbreviation for: */
  94. log_start = 0;
  95. must_log = 1;
  96. }
  97. inr = 0;
  98. }
  99. /******** The log file ********/
  100. open_log(firsttime)
  101. int firsttime;
  102. {
  103. if (!firsttime) {
  104. sprintf(logvar, "%s%ld", logvar, mess_id);
  105. if (log_fp) {
  106. fclose(log_fp);
  107. log_fp = 0;
  108. }
  109. logging = 0;
  110. if ((must_log = getpar(logvar) != 0)) {
  111. sprintf(log_file, "%s%ld", log_file, mess_id);
  112. log_start = atol(getpar(logvar));
  113. }
  114. }
  115. else {
  116. /* first time, top level */
  117. logvar = "LOG\0 ";
  118. if (at) { /* patch */
  119. must_log = 1;
  120. log_start = at - 1;
  121. }
  122. else
  123. if (!must_log && (must_log = getpar(logvar) != 0)) {
  124. log_start = atoi(getpar(logvar));
  125. }
  126. set_lmask(lmask ? lmask :
  127. getpar("LOGMASK") ? getpar("LOGMASK") :
  128. "A-Z9d2twx9");
  129. }
  130. /* Create logfile if needed */
  131. if (must_log) {
  132. if ((log_fp = fcreat_high(log_file)) == NULL)
  133. fatal("Cannot create logfile '%s'", log_file);
  134. }
  135. if (must_log && inr >= log_start) {
  136. logging = 1;
  137. }
  138. }
  139. close_log() {
  140. if (log_fp) {
  141. fclose(log_fp);
  142. log_fp = 0;
  143. }
  144. }
  145. /******** The logmask ********/
  146. #define inrange(c,l,h) (l <= c && c <= h)
  147. #define layout(c) (c == ' ' || c == '\t' || c == ',')
  148. PRIVATE set_lmask(mask)
  149. char *mask;
  150. {
  151. register char *mp = mask;
  152. while (*mp != 0) {
  153. register char *lvp;
  154. register int lev;
  155. while (layout(*mp)) {
  156. mp++;
  157. }
  158. /* find level */
  159. lvp = mp;
  160. while (*lvp != 0 && !inrange(*lvp, '0', '9')) {
  161. lvp++;
  162. }
  163. lev = *lvp - '0';
  164. /* find classes */
  165. while (mp != lvp) {
  166. register mc = *mp;
  167. if ( inrange(mc, 'a', 'z')
  168. || inrange(mc, 'A', 'Z')
  169. || mc == '+'
  170. || mc == '*'
  171. ) {
  172. log_level[mc] = lev;
  173. mp++;
  174. }
  175. else if (mc == '-') {
  176. register char c;
  177. for (c = *(mp-1) + 1; c <= *(mp + 1); c++) {
  178. log_level[c] = lev;
  179. }
  180. mp += 2;
  181. }
  182. else if (layout(mc)) {
  183. mp++;
  184. }
  185. else fatal("Bad logmask initialization string");
  186. }
  187. mp = lvp + 1;
  188. }
  189. }
  190. /******** The logging ********/
  191. int check_log(mark)
  192. char mark[];
  193. {
  194. /* mark must be of the form ".CL...", C is class letter,
  195. L is level digit.
  196. */
  197. if (!logging)
  198. return 0;
  199. return ((mark[2] - '0') <= log_level[mark[1]]);
  200. }
  201. #if __STDC__
  202. /*VARARGS*/
  203. do_log(char *fmt, ...)
  204. {
  205. va_list ap;
  206. va_start(ap, fmt);
  207. {
  208. #else
  209. /*VARARGS*/
  210. do_log(va_alist)
  211. va_dcl
  212. {
  213. va_list ap;
  214. va_start(ap);
  215. {
  216. char *fmt = va_arg(ap, char *);
  217. #endif
  218. if (!check_log(fmt))
  219. return;
  220. if (fmt[0] == '@') {
  221. /* include position */
  222. fprintf(log_fp, "%.4s%s, ", fmt, position());
  223. vfprintf(log_fp, &fmt[4], ap);
  224. }
  225. else {
  226. vfprintf(log_fp, &fmt[0], ap);
  227. }
  228. }
  229. va_end(ap);
  230. putc('\n', log_fp);
  231. }
  232. log_eoi()
  233. {
  234. /* Logging to be done at end of instruction */
  235. if (logging) {
  236. if (inr == gdump)
  237. gdad_all(gmin, gmax);
  238. if (inr == hdump)
  239. hpd_all();
  240. std_all(stdsize, stdrawflag);
  241. }
  242. if (inr == stop) {
  243. message("program stopped on request");
  244. close_down(0);
  245. }
  246. }
  247. /******** Service routines ********/
  248. PRIVATE char *getpar(var)
  249. char *var;
  250. {
  251. /* Looks up the name in the argument list.
  252. */
  253. register int count;
  254. register int ln = strlen(var);
  255. for (count = 0; count < argcount; count++) {
  256. register char *arg = arglist[count];
  257. if (strncmp(var, arg, ln) == 0 && arg[ln] == '=') {
  258. return &arg[ln+1];
  259. }
  260. }
  261. return 0;
  262. }
  263. PRIVATE long longpar(var, def)
  264. char *var; /* name of the variable */
  265. long def; /* default value */
  266. {
  267. register char *res = getpar(var);
  268. return (res ? atol(res) : def);
  269. }
  270. #endif /* LOGGING */