trace.c revision 90744
1/* $OpenBSD: trace.c,v 1.4 2002/02/16 21:27:48 millert Exp $ */ 2/* 3 * Copyright (c) 2001 Marc Espie. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE OPENBSD PROJECT AND CONTRIBUTORS 15 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OPENBSD 18 * PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/types.h> 28#include <stddef.h> 29#include <stdio.h> 30#include <err.h> 31#include <stdlib.h> 32#include "mdef.h" 33#include "stdd.h" 34#include "extern.h" 35 36FILE *traceout = stderr; 37 38int traced_macros = 0; 39 40#define TRACE_ARGS 1 41#define TRACE_EXPANSION 2 42#define TRACE_QUOTE 4 43#define TRACE_FILENAME 8 44#define TRACE_LINENO 16 45#define TRACE_CONT 32 46#define TRACE_ID 64 47#define TRACE_NEWFILE 128 /* not implemented yet */ 48#define TRACE_INPUT 256 /* not implemented yet */ 49#define TRACE_ALL 512 50 51static struct t { 52 struct t *next; 53 char *name; 54 int on; 55} *l; 56 57static unsigned int letter_to_flag(int); 58static void print_header(struct input_file *); 59static struct t *find_trace_entry(const char *); 60static int frame_level(void); 61 62static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION; 63 64static struct t * 65find_trace_entry(name) 66 const char *name; 67{ 68 struct t *n; 69 70 for (n = l; n != NULL; n = n->next) 71 if (STREQ(n->name, name)) 72 return n; 73 return NULL; 74} 75 76 77void 78mark_traced(name, on) 79 const char *name; 80 int on; 81{ 82 struct t *n, *n2; 83 84 traced_macros = 1; 85 86 if (name == NULL) { 87 if (on) 88 flags |= TRACE_ALL; 89 else { 90 flags &= ~TRACE_ALL; 91 traced_macros = 0; 92 } 93 for (n = l; n != NULL; n = n2) { 94 n2 = n->next; 95 free(n->name); 96 free(n); 97 } 98 l = NULL; 99 } else { 100 n = find_trace_entry(name); 101 if (n == NULL) { 102 n = xalloc(sizeof(struct t)); 103 n->name = xstrdup(name); 104 n->next = l; 105 l = n; 106 } 107 n->on = on; 108 } 109} 110 111int 112is_traced(name) 113 const char *name; 114{ 115 struct t *n; 116 117 for (n = l; n != NULL; n = n->next) 118 if (STREQ(n->name, name)) 119 return n->on; 120 return (flags & TRACE_ALL) ? 1 : 0; 121} 122 123void 124trace_file(name) 125 const char *name; 126{ 127 128 if (traceout != stderr) 129 fclose(traceout); 130 traceout = fopen(name, "w"); 131 if (!traceout) 132 err(1, "can't open %s", name); 133} 134 135static unsigned int 136letter_to_flag(c) 137 int c; 138{ 139 switch(c) { 140 case 'a': 141 return TRACE_ARGS; 142 case 'e': 143 return TRACE_EXPANSION; 144 case 'q': 145 return TRACE_QUOTE; 146 case 'c': 147 return TRACE_CONT; 148 case 'x': 149 return TRACE_ID; 150 case 'f': 151 return TRACE_FILENAME; 152 case 'l': 153 return TRACE_LINENO; 154 case 'p': 155 return TRACE_NEWFILE; 156 case 'i': 157 return TRACE_INPUT; 158 case 't': 159 return TRACE_ALL; 160 case 'V': 161 return ~0; 162 default: 163 return 0; 164 } 165} 166 167void 168set_trace_flags(s) 169 const char *s; 170{ 171 char mode = 0; 172 unsigned int f = 0; 173 174 traced_macros = 1; 175 176 if (*s == '+' || *s == '-') 177 mode = *s++; 178 while (*s) 179 f |= letter_to_flag(*s++); 180 switch(mode) { 181 case 0: 182 flags = f; 183 break; 184 case '+': 185 flags |= f; 186 break; 187 case '-': 188 flags &= ~f; 189 break; 190 } 191} 192 193static int 194frame_level() 195{ 196 int level; 197 int framep; 198 199 for (framep = fp, level = 0; framep != 0; 200 level++,framep = mstack[framep-2].sfra) 201 ; 202 return level; 203} 204 205static void 206print_header(inp) 207 struct input_file *inp; 208{ 209 fprintf(traceout, "m4trace:"); 210 if (flags & TRACE_FILENAME) 211 fprintf(traceout, "%s:", inp->name); 212 if (flags & TRACE_LINENO) 213 fprintf(traceout, "%lu:", inp->lineno); 214 fprintf(traceout, " -%d- ", frame_level()); 215 if (flags & TRACE_ID) 216 fprintf(traceout, "id %lu: ", expansion_id); 217} 218 219ssize_t 220trace(argv, argc, inp) 221 const char **argv; 222 int argc; 223 struct input_file *inp; 224{ 225 print_header(inp); 226 if (flags & TRACE_CONT) { 227 fprintf(traceout, "%s ...\n", argv[1]); 228 print_header(inp); 229 } 230 fprintf(traceout, "%s", argv[1]); 231 if ((flags & TRACE_ARGS) && argc > 2) { 232 char delim[3]; 233 int i; 234 235 delim[0] = LPAREN; 236 delim[1] = EOS; 237 for (i = 2; i < argc; i++) { 238 fprintf(traceout, "%s%s%s%s", delim, 239 (flags & TRACE_QUOTE) ? lquote : "", 240 argv[i], 241 (flags & TRACE_QUOTE) ? rquote : ""); 242 delim[0] = COMMA; 243 delim[1] = ' '; 244 delim[2] = EOS; 245 } 246 fprintf(traceout, "%c", RPAREN); 247 } 248 if (flags & TRACE_CONT) { 249 fprintf(traceout, " -> ???\n"); 250 print_header(inp); 251 fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]); 252 } 253 if (flags & TRACE_EXPANSION) 254 return buffer_mark(); 255 else { 256 fprintf(traceout, "\n"); 257 return -1; 258 } 259} 260 261void 262finish_trace(mark) 263size_t mark; 264{ 265 fprintf(traceout, " -> "); 266 if (flags & TRACE_QUOTE) 267 fprintf(traceout, "%s", lquote); 268 dump_buffer(traceout, mark); 269 if (flags & TRACE_QUOTE) 270 fprintf(traceout, "%s", rquote); 271 fprintf(traceout, "\n"); 272} 273