log.c 5.9 KB

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