[BACK]Return to trace.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / m4

Annotation of src/usr.bin/m4/trace.c, Revision 1.7

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