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