/* * Copyright (c) 2012, Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Intel Corporation nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #define _GNU_SOURCE #include #include #include #include #include #include #define RD 0 #define WR 1 typedef enum { TOKEN_ERROR = -1, TOKEN_LINEMARKER, /* a preprocessor line marker */ TOKEN_BLOCK, /* a block enclosed in {}/()/[] */ TOKEN_WORD, /* a word */ TOKEN_DQUOTED, /* a double-quoted sequence */ TOKEN_SQUOTED, /* a single-quoted sequence */ TOKEN_ASSIGN, /* '=' */ TOKEN_SEMICOLON, /* ';' */ TOKEN_COLON, /* ',' */ TOKEN_OTHER, /* any other token */ } token_type_t; typedef struct { token_type_t type; /* token type */ char *value; /* token value */ } token_t; #define READBUF_SIZE ( 8 * 1024) #define RINGBUF_SIZE (16 * 1024) #define MAX_TOKEN (512) #define MAX_TOKENS (64) typedef struct { int fd; /* file descriptor to read */ char buf[READBUF_SIZE]; /* data buffer */ int len; /* amount of data in buffer */ int rd; /* data buffer read offset */ int nxt; /* pushed back data if non-zero */ } input_t; typedef struct { char buf[RINGBUF_SIZE]; /* data buffer */ int wr; /* write offset */ } ringbuf_t; typedef struct { char *preproc; /* preprocessor to use */ char *pattern; /* symbol pattern */ char **files; /* files to parse for symbols */ int nfile; /* number of files */ char *cflags; /* compiler flags */ char *output; /* output path */ int gnuld; /* generate GNU ld script */ int verbose; /* verbosity */ } config_t; typedef struct { char **syms; int nsym; } symtab_t; static int verbosity = 1; static void fatal_error(const char *fmt, ...) { va_list ap; va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); exit(1); } static void verbose_message(int level, const char *fmt, ...) { va_list ap; if (verbosity >= level) { va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); } } static char *unshave(char *cmd) { #define SHAVE "shave cc " char *shave; shave = strstr(cmd, SHAVE); if (shave == NULL) return cmd; else return shave + sizeof(SHAVE) - 1; #undef SHAVE } static void print_usage(const char *argv0, int exit_code, const char *fmt, ...) { va_list ap; if (fmt && *fmt) { va_start(ap, fmt); vprintf(fmt, ap); va_end(ap); } printf("usage: %s [options]\n\n" "The possible options are:\n" " -P --preproc preprocessor to use [gcc]\n" " -c, --compiler-flags flags to pass to compiler\n" " -p, --pattern symbol regexp pattern\n" " -o, --output write output to the given file\n" " -g, --gnu-ld