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