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