1*a841e1ebSBaptiste Daroussin /* $OpenBSD: trace.c,v 1.16 2010/09/07 19:58:09 marco 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 */ 26acc9d408SJuli Mallett #include <sys/cdefs.h> 27acc9d408SJuli Mallett __FBSDID("$FreeBSD$"); 28acc9d408SJuli Mallett 29e3d86717SJuli Mallett #include <err.h> 30*a841e1ebSBaptiste Daroussin #include <stddef.h> 31*a841e1ebSBaptiste Daroussin #include <stdint.h> 32*a841e1ebSBaptiste Daroussin #include <stdio.h> 33e3d86717SJuli Mallett #include <stdlib.h> 34e3d86717SJuli Mallett #include "mdef.h" 35e3d86717SJuli Mallett #include "stdd.h" 36e3d86717SJuli Mallett #include "extern.h" 37e3d86717SJuli Mallett 38acc9d408SJuli Mallett FILE *traceout; 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 50e3d86717SJuli Mallett static unsigned int letter_to_flag(int); 51e3d86717SJuli Mallett static void print_header(struct input_file *); 52e3d86717SJuli Mallett static int frame_level(void); 53e3d86717SJuli Mallett 54e3d86717SJuli Mallett 55*a841e1ebSBaptiste Daroussin unsigned int trace_flags = TRACE_QUOTE | TRACE_EXPANSION; 56e3d86717SJuli Mallett 57e3d86717SJuli Mallett void 58bd2bfb58SJuli Mallett trace_file(const char *name) 59e3d86717SJuli Mallett { 60e3d86717SJuli Mallett 61*a841e1ebSBaptiste Daroussin if (traceout && traceout != stderr) 62e3d86717SJuli Mallett fclose(traceout); 63e3d86717SJuli Mallett traceout = fopen(name, "w"); 64e3d86717SJuli Mallett if (!traceout) 65e3d86717SJuli Mallett err(1, "can't open %s", name); 66e3d86717SJuli Mallett } 67e3d86717SJuli Mallett 68e3d86717SJuli Mallett static unsigned int 69bd2bfb58SJuli Mallett letter_to_flag(int c) 70e3d86717SJuli Mallett { 71e3d86717SJuli Mallett switch(c) { 72e3d86717SJuli Mallett case 'a': 73e3d86717SJuli Mallett return TRACE_ARGS; 74e3d86717SJuli Mallett case 'e': 75e3d86717SJuli Mallett return TRACE_EXPANSION; 76e3d86717SJuli Mallett case 'q': 77e3d86717SJuli Mallett return TRACE_QUOTE; 78e3d86717SJuli Mallett case 'c': 79e3d86717SJuli Mallett return TRACE_CONT; 80e3d86717SJuli Mallett case 'x': 81e3d86717SJuli Mallett return TRACE_ID; 82e3d86717SJuli Mallett case 'f': 83e3d86717SJuli Mallett return TRACE_FILENAME; 84e3d86717SJuli Mallett case 'l': 85e3d86717SJuli Mallett return TRACE_LINENO; 86e3d86717SJuli Mallett case 'p': 87e3d86717SJuli Mallett return TRACE_NEWFILE; 88e3d86717SJuli Mallett case 'i': 89e3d86717SJuli Mallett return TRACE_INPUT; 90e3d86717SJuli Mallett case 't': 91e3d86717SJuli Mallett return TRACE_ALL; 92e3d86717SJuli Mallett case 'V': 93e3d86717SJuli Mallett return ~0; 94e3d86717SJuli Mallett default: 95e3d86717SJuli Mallett return 0; 96e3d86717SJuli Mallett } 97e3d86717SJuli Mallett } 98e3d86717SJuli Mallett 99e3d86717SJuli Mallett void 100bd2bfb58SJuli Mallett set_trace_flags(const char *s) 101e3d86717SJuli Mallett { 102e3d86717SJuli Mallett char mode = 0; 103e3d86717SJuli Mallett unsigned int f = 0; 104e3d86717SJuli Mallett 105e3d86717SJuli Mallett if (*s == '+' || *s == '-') 106e3d86717SJuli Mallett mode = *s++; 107e3d86717SJuli Mallett while (*s) 108e3d86717SJuli Mallett f |= letter_to_flag(*s++); 109e3d86717SJuli Mallett switch(mode) { 110e3d86717SJuli Mallett case 0: 111*a841e1ebSBaptiste Daroussin trace_flags = f; 112e3d86717SJuli Mallett break; 113e3d86717SJuli Mallett case '+': 114*a841e1ebSBaptiste Daroussin trace_flags |= f; 115e3d86717SJuli Mallett break; 116e3d86717SJuli Mallett case '-': 117*a841e1ebSBaptiste Daroussin trace_flags &= ~f; 118e3d86717SJuli Mallett break; 119e3d86717SJuli Mallett } 120e3d86717SJuli Mallett } 121e3d86717SJuli Mallett 122e3d86717SJuli Mallett static int 123d1fea89cSJuli Mallett frame_level(void) 124e3d86717SJuli Mallett { 125e3d86717SJuli Mallett int level; 126e3d86717SJuli Mallett int framep; 127e3d86717SJuli Mallett 128e3d86717SJuli Mallett for (framep = fp, level = 0; framep != 0; 129*a841e1ebSBaptiste Daroussin level++,framep = mstack[framep-3].sfra) 130e3d86717SJuli Mallett ; 131e3d86717SJuli Mallett return level; 132e3d86717SJuli Mallett } 133e3d86717SJuli Mallett 134e3d86717SJuli Mallett static void 135bd2bfb58SJuli Mallett print_header(struct input_file *inp) 136e3d86717SJuli Mallett { 137e3d86717SJuli Mallett fprintf(traceout, "m4trace:"); 138*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_FILENAME) 139e3d86717SJuli Mallett fprintf(traceout, "%s:", inp->name); 140*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_LINENO) 141e3d86717SJuli Mallett fprintf(traceout, "%lu:", inp->lineno); 142e3d86717SJuli Mallett fprintf(traceout, " -%d- ", frame_level()); 143*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_ID) 144e3d86717SJuli Mallett fprintf(traceout, "id %lu: ", expansion_id); 145e3d86717SJuli Mallett } 146e3d86717SJuli Mallett 147*a841e1ebSBaptiste Daroussin size_t 148bd2bfb58SJuli Mallett trace(const char *argv[], int argc, struct input_file *inp) 149e3d86717SJuli Mallett { 150*a841e1ebSBaptiste Daroussin if (!traceout) 151*a841e1ebSBaptiste Daroussin traceout = stderr; 152e3d86717SJuli Mallett print_header(inp); 153*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_CONT) { 154e3d86717SJuli Mallett fprintf(traceout, "%s ...\n", argv[1]); 155e3d86717SJuli Mallett print_header(inp); 156e3d86717SJuli Mallett } 157e3d86717SJuli Mallett fprintf(traceout, "%s", argv[1]); 158*a841e1ebSBaptiste Daroussin if ((trace_flags & TRACE_ARGS) && argc > 2) { 159e3d86717SJuli Mallett char delim[3]; 160e3d86717SJuli Mallett int i; 161e3d86717SJuli Mallett 162e3d86717SJuli Mallett delim[0] = LPAREN; 163e3d86717SJuli Mallett delim[1] = EOS; 164e3d86717SJuli Mallett for (i = 2; i < argc; i++) { 165e3d86717SJuli Mallett fprintf(traceout, "%s%s%s%s", delim, 166*a841e1ebSBaptiste Daroussin (trace_flags & TRACE_QUOTE) ? lquote : "", 167e3d86717SJuli Mallett argv[i], 168*a841e1ebSBaptiste Daroussin (trace_flags & TRACE_QUOTE) ? rquote : ""); 169e3d86717SJuli Mallett delim[0] = COMMA; 170e3d86717SJuli Mallett delim[1] = ' '; 171e3d86717SJuli Mallett delim[2] = EOS; 172e3d86717SJuli Mallett } 173e3d86717SJuli Mallett fprintf(traceout, "%c", RPAREN); 174e3d86717SJuli Mallett } 175*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_CONT) { 176e3d86717SJuli Mallett fprintf(traceout, " -> ???\n"); 177e3d86717SJuli Mallett print_header(inp); 178e3d86717SJuli Mallett fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]); 179e3d86717SJuli Mallett } 180*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_EXPANSION) 181e3d86717SJuli Mallett return buffer_mark(); 182e3d86717SJuli Mallett else { 183e3d86717SJuli Mallett fprintf(traceout, "\n"); 184*a841e1ebSBaptiste Daroussin return SIZE_MAX; 185e3d86717SJuli Mallett } 186e3d86717SJuli Mallett } 187e3d86717SJuli Mallett 188e3d86717SJuli Mallett void 189bd2bfb58SJuli Mallett finish_trace(size_t mark) 190e3d86717SJuli Mallett { 191e3d86717SJuli Mallett fprintf(traceout, " -> "); 192*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_QUOTE) 193e3d86717SJuli Mallett fprintf(traceout, "%s", lquote); 194e3d86717SJuli Mallett dump_buffer(traceout, mark); 195*a841e1ebSBaptiste Daroussin if (trace_flags & TRACE_QUOTE) 196e3d86717SJuli Mallett fprintf(traceout, "%s", rquote); 197e3d86717SJuli Mallett fprintf(traceout, "\n"); 198e3d86717SJuli Mallett } 199