trace.c revision 95060
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/cdefs.h> 28__FBSDID("$FreeBSD: head/usr.bin/m4/trace.c 95060 2002-04-19 17:26:21Z jmallett $"); 29 30#include <sys/types.h> 31#include <stddef.h> 32#include <stdio.h> 33#include <err.h> 34#include <stdlib.h> 35#include "mdef.h" 36#include "stdd.h" 37#include "extern.h" 38 39FILE *traceout; 40 41int traced_macros = 0; 42 43#define TRACE_ARGS 1 44#define TRACE_EXPANSION 2 45#define TRACE_QUOTE 4 46#define TRACE_FILENAME 8 47#define TRACE_LINENO 16 48#define TRACE_CONT 32 49#define TRACE_ID 64 50#define TRACE_NEWFILE 128 /* not implemented yet */ 51#define TRACE_INPUT 256 /* not implemented yet */ 52#define TRACE_ALL 512 53 54static struct t { 55 struct t *next; 56 char *name; 57 int on; 58} *l; 59 60static unsigned int letter_to_flag(int); 61static void print_header(struct input_file *); 62static struct t *find_trace_entry(const char *); 63static int frame_level(void); 64 65static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION; 66 67static struct t * 68find_trace_entry(name) 69 const char *name; 70{ 71 struct t *n; 72 73 for (n = l; n != NULL; n = n->next) 74 if (STREQ(n->name, name)) 75 return n; 76 return NULL; 77} 78 79 80void 81mark_traced(name, on) 82 const char *name; 83 int on; 84{ 85 struct t *n, *n2; 86 87 traced_macros = 1; 88 89 if (name == NULL) { 90 if (on) 91 flags |= TRACE_ALL; 92 else { 93 flags &= ~TRACE_ALL; 94 traced_macros = 0; 95 } 96 for (n = l; n != NULL; n = n2) { 97 n2 = n->next; 98 free(n->name); 99 free(n); 100 } 101 l = NULL; 102 } else { 103 n = find_trace_entry(name); 104 if (n == NULL) { 105 n = xalloc(sizeof(struct t)); 106 n->name = xstrdup(name); 107 n->next = l; 108 l = n; 109 } 110 n->on = on; 111 } 112} 113 114int 115is_traced(name) 116 const char *name; 117{ 118 struct t *n; 119 120 for (n = l; n != NULL; n = n->next) 121 if (STREQ(n->name, name)) 122 return n->on; 123 return (flags & TRACE_ALL) ? 1 : 0; 124} 125 126void 127trace_file(name) 128 const char *name; 129{ 130 131 if (traceout != stderr) 132 fclose(traceout); 133 traceout = fopen(name, "w"); 134 if (!traceout) 135 err(1, "can't open %s", name); 136} 137 138static unsigned int 139letter_to_flag(c) 140 int c; 141{ 142 switch(c) { 143 case 'a': 144 return TRACE_ARGS; 145 case 'e': 146 return TRACE_EXPANSION; 147 case 'q': 148 return TRACE_QUOTE; 149 case 'c': 150 return TRACE_CONT; 151 case 'x': 152 return TRACE_ID; 153 case 'f': 154 return TRACE_FILENAME; 155 case 'l': 156 return TRACE_LINENO; 157 case 'p': 158 return TRACE_NEWFILE; 159 case 'i': 160 return TRACE_INPUT; 161 case 't': 162 return TRACE_ALL; 163 case 'V': 164 return ~0; 165 default: 166 return 0; 167 } 168} 169 170void 171set_trace_flags(s) 172 const char *s; 173{ 174 char mode = 0; 175 unsigned int f = 0; 176 177 traced_macros = 1; 178 179 if (*s == '+' || *s == '-') 180 mode = *s++; 181 while (*s) 182 f |= letter_to_flag(*s++); 183 switch(mode) { 184 case 0: 185 flags = f; 186 break; 187 case '+': 188 flags |= f; 189 break; 190 case '-': 191 flags &= ~f; 192 break; 193 } 194} 195 196static int 197frame_level() 198{ 199 int level; 200 int framep; 201 202 for (framep = fp, level = 0; framep != 0; 203 level++,framep = mstack[framep-2].sfra) 204 ; 205 return level; 206} 207 208static void 209print_header(inp) 210 struct input_file *inp; 211{ 212 fprintf(traceout, "m4trace:"); 213 if (flags & TRACE_FILENAME) 214 fprintf(traceout, "%s:", inp->name); 215 if (flags & TRACE_LINENO) 216 fprintf(traceout, "%lu:", inp->lineno); 217 fprintf(traceout, " -%d- ", frame_level()); 218 if (flags & TRACE_ID) 219 fprintf(traceout, "id %lu: ", expansion_id); 220} 221 222ssize_t 223trace(argv, argc, inp) 224 const char **argv; 225 int argc; 226 struct input_file *inp; 227{ 228 print_header(inp); 229 if (flags & TRACE_CONT) { 230 fprintf(traceout, "%s ...\n", argv[1]); 231 print_header(inp); 232 } 233 fprintf(traceout, "%s", argv[1]); 234 if ((flags & TRACE_ARGS) && argc > 2) { 235 char delim[3]; 236 int i; 237 238 delim[0] = LPAREN; 239 delim[1] = EOS; 240 for (i = 2; i < argc; i++) { 241 fprintf(traceout, "%s%s%s%s", delim, 242 (flags & TRACE_QUOTE) ? lquote : "", 243 argv[i], 244 (flags & TRACE_QUOTE) ? rquote : ""); 245 delim[0] = COMMA; 246 delim[1] = ' '; 247 delim[2] = EOS; 248 } 249 fprintf(traceout, "%c", RPAREN); 250 } 251 if (flags & TRACE_CONT) { 252 fprintf(traceout, " -> ???\n"); 253 print_header(inp); 254 fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]); 255 } 256 if (flags & TRACE_EXPANSION) 257 return buffer_mark(); 258 else { 259 fprintf(traceout, "\n"); 260 return -1; 261 } 262} 263 264void 265finish_trace(mark) 266size_t mark; 267{ 268 fprintf(traceout, " -> "); 269 if (flags & TRACE_QUOTE) 270 fprintf(traceout, "%s", lquote); 271 dump_buffer(traceout, mark); 272 if (flags & TRACE_QUOTE) 273 fprintf(traceout, "%s", rquote); 274 fprintf(traceout, "\n"); 275} 276