1 /* $OpenBSD: trace.c,v 1.1 2001/09/18 14:55:52 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/types.h> 28 #include <stddef.h> 29 #include <stdio.h> 30 #include <err.h> 31 #include "mdef.h" 32 #include "stdd.h" 33 #include "extern.h" 34 35 FILE *traceout = stderr; 36 37 int traced_macros = 0; 38 39 #define TRACE_ARGS 1 40 #define TRACE_EXPANSION 2 41 #define TRACE_QUOTE 4 42 #define TRACE_FILENAME 8 43 #define TRACE_LINENO 16 44 #define TRACE_CONT 32 45 #define TRACE_ID 64 46 #define TRACE_NEWFILE 128 /* not implemented yet */ 47 #define TRACE_INPUT 256 /* not implemented yet */ 48 #define TRACE_ALL 512 49 50 51 static unsigned int letter_to_flag __P((int)); 52 static void print_header __P((struct input_file *)); 53 54 static unsigned int flags = TRACE_QUOTE | TRACE_EXPANSION; 55 56 static struct t { 57 struct t *next; 58 char *name; 59 } *l; 60 61 void 62 mark_traced(name) 63 const char *name; 64 { 65 struct t *n; 66 67 traced_macros = 1; 68 n = xalloc(sizeof(struct t)); 69 n->name = xstrdup(name); 70 n->next = l; 71 l = n; 72 } 73 74 75 int 76 is_traced(name) 77 const char *name; 78 { 79 struct t *n; 80 81 if (flags & TRACE_ALL) 82 return 1; 83 for (n = l; n != NULL; n = n->next) 84 if (STREQ(n->name, name)) 85 return 1; 86 return 0; 87 } 88 89 void 90 trace_file(name) 91 const char *name; 92 { 93 94 if (traceout != stderr) 95 fclose(traceout); 96 traceout = fopen(name, "w"); 97 if (!traceout) 98 err(1, "can't open %s", name); 99 } 100 101 static unsigned int 102 letter_to_flag(c) 103 int c; 104 { 105 switch(c) { 106 case 'a': 107 return TRACE_ARGS; 108 case 'e': 109 return TRACE_EXPANSION; 110 case 'q': 111 return TRACE_QUOTE; 112 case 'c': 113 return TRACE_CONT; 114 case 'x': 115 return TRACE_ID; 116 case 'f': 117 return TRACE_FILENAME; 118 case 'l': 119 return TRACE_LINENO; 120 case 'p': 121 return TRACE_NEWFILE; 122 case 'i': 123 return TRACE_INPUT; 124 case 't': 125 return TRACE_ALL; 126 case 'V': 127 return ~0; 128 default: 129 return 0; 130 } 131 } 132 133 void 134 set_trace_flags(s) 135 const char *s; 136 { 137 char mode = 0; 138 unsigned int f = 0; 139 140 traced_macros = 1; 141 142 if (*s == '+' || *s == '-') 143 mode = *s++; 144 while (*s) 145 f |= letter_to_flag(*s++); 146 switch(mode) { 147 case 0: 148 flags = f; 149 break; 150 case '+': 151 flags |= f; 152 break; 153 case '-': 154 flags &= ~f; 155 break; 156 } 157 } 158 159 static void 160 print_header(inp) 161 struct input_file *inp; 162 { 163 fprintf(traceout, "m4trace:"); 164 if (flags & TRACE_FILENAME) 165 fprintf(traceout, "%s:", inp->name); 166 if (flags & TRACE_LINENO) 167 fprintf(traceout, "%lu:", inp->lineno); 168 fprintf(traceout, " -1- "); 169 if (flags & TRACE_ID) 170 fprintf(traceout, "id %lu: ", expansion_id); 171 } 172 173 ssize_t 174 trace(argv, argc, inp) 175 const char **argv; 176 int argc; 177 struct input_file *inp; 178 { 179 print_header(inp); 180 if (flags & TRACE_CONT) { 181 fprintf(traceout, "%s ...\n", argv[1]); 182 print_header(inp); 183 } 184 fprintf(traceout, "%s", argv[1]); 185 if ((flags & TRACE_ARGS) && argc > 2) { 186 char delim = LPAREN; 187 int i; 188 189 for (i = 2; i < argc; i++) { 190 fprintf(traceout, "%c%s%s%s", delim, 191 (flags & TRACE_QUOTE) ? lquote : "", 192 argv[i], 193 (flags & TRACE_QUOTE) ? rquote : ""); 194 delim = COMMA; 195 } 196 fprintf(traceout, "%c", RPAREN); 197 } 198 if (flags & TRACE_CONT) { 199 fprintf(traceout, " -> ???\n"); 200 print_header(inp); 201 fprintf(traceout, argc > 2 ? "%s(...)" : "%s", argv[1]); 202 } 203 if (flags & TRACE_EXPANSION) 204 return buffer_mark(); 205 else { 206 fprintf(traceout, "\n"); 207 return -1; 208 } 209 } 210 211 void 212 finish_trace(mark) 213 size_t mark; 214 { 215 fprintf(traceout, " -> "); 216 if (flags & TRACE_QUOTE) 217 fprintf(traceout, "%s", lquote); 218 dump_buffer(traceout, mark); 219 if (flags & TRACE_QUOTE) 220 fprintf(traceout, "%s", rquote); 221 fprintf(traceout, "\n"); 222 } 223