Mercurial > hg > index.cgi
view lwcc/cc-main.c @ 508:10f62dc61a75
Fix bad usage of sprintf()
Usage of sprintf() to append to a string in the form of
sprintf(buf, "%s...", buf...) is undefined, regardless whether it
worked on a lot of older systems. It was always a bad idea and it
now breaks on current glibc and gcc development environments.
The moral: if any of your code uses sprintf() in a way similar to
the above, fix it. It may not fail in a benign way.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sun, 10 May 2020 22:38:24 -0600 |
parents | c3099c5d9d3e |
children |
line wrap: on
line source
/* lwcc/cpp-main.c Copyright © 2013 William Astle This file is part of LWTOOLS. LWTOOLS is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include <errno.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <lw_stringlist.h> #include <lw_cmdline.h> #include <lw_string.h> #include <version.h> #include "cpp.h" #include "tree.h" node_t *process_file(const char *); static void do_error(const char *f, ...); extern node_t *parse_program(struct preproc_info *pp); extern void generate_code(node_t *n, FILE *of); node_t *program_tree = NULL; /* command line option handling */ #define PROGVER "lwcc-cc from " PACKAGE_STRING char *program_name; /* input files */ lw_stringlist_t input_files; lw_stringlist_t includedirs; lw_stringlist_t sysincludedirs; lw_stringlist_t macrolist; /* various flags */ int trigraphs = 0; char *output_file = NULL; FILE *output_fp = NULL; static struct lw_cmdline_options options[] = { { "output", 'o', "FILE", 0, "Output to FILE"}, { "include", 'i', "FILE", 0, "Pre-include FILE" }, { "includedir", 'I', "PATH", 0, "Add entry to the user include path" }, { "sincludedir", 'S', "PATH", 0, "Add entry to the system include path" }, { "define", 'D', "SYM[=VAL]",0, "Automatically define SYM to be VAL (or 1)"}, { "trigraphs", 0x100, NULL, 0, "Enable interpretation of trigraphs" }, { 0 } }; static int parse_opts(int key, char *arg, void *state) { switch (key) { case 'o': if (output_file) do_error("Output file specified more than once."); output_file = arg; break; case 0x100: trigraphs = 1; break; case 'I': lw_stringlist_addstring(includedirs, arg); break; case 'S': lw_stringlist_addstring(sysincludedirs, arg); break; case 'D': lw_stringlist_addstring(macrolist, arg); break; case lw_cmdline_key_end: break; case lw_cmdline_key_arg: lw_stringlist_addstring(input_files, arg); break; default: return lw_cmdline_err_unknown; } return 0; } static struct lw_cmdline_parser cmdline_parser = { options, parse_opts, "INPUTFILE", "lwcc-cc - C compiler for lwcc", PROGVER }; int main(int argc, char **argv) { program_name = argv[0]; int retval = 0; node_t *n; input_files = lw_stringlist_create(); includedirs = lw_stringlist_create(); sysincludedirs = lw_stringlist_create(); macrolist = lw_stringlist_create(); /* parse command line arguments */ lw_cmdline_parse(&cmdline_parser, argc, argv, 0, 0, NULL); /* set up output file */ if (output_file == NULL || strcmp(output_file, "-") == 0) { output_fp = stdout; } else { output_fp = fopen(output_file, "wb"); if (output_fp == NULL) { do_error("Failed to create output file %s: %s", output_file, strerror(errno)); } } program_tree = node_create(NODE_PROGRAM); if (lw_stringlist_nstrings(input_files) == 0) { /* if no input files, work on stdin */ n = process_file("-"); if (!n) retval = 1; else node_addchild(program_tree, n); } else { char *s; lw_stringlist_reset(input_files); for (s = lw_stringlist_current(input_files); s; s = lw_stringlist_next(input_files)) { n = process_file(s); if (!n) retval = 1; if (retval != 0) break; node_addchild(program_tree, n); } } lw_stringlist_destroy(input_files); lw_stringlist_destroy(includedirs); lw_stringlist_destroy(sysincludedirs); lw_stringlist_destroy(macrolist); node_display(program_tree, stdout); // generate output generate_code(program_tree, output_fp); node_destroy(program_tree); exit(retval); } node_t *process_file(const char *fn) { struct preproc_info *pp; char *tstr; node_t *n; pp = preproc_init(fn); if (!pp) return NULL; /* set up the include paths */ lw_stringlist_reset(includedirs); for (tstr = lw_stringlist_current(includedirs); tstr; tstr = lw_stringlist_next(includedirs)) { preproc_add_include(pp, tstr, 0); } lw_stringlist_reset(sysincludedirs); for (tstr = lw_stringlist_current(sysincludedirs); tstr; tstr = lw_stringlist_next(sysincludedirs)) { preproc_add_include(pp, tstr, 1); } /* set up pre-defined macros */ lw_stringlist_reset(macrolist); for (tstr = lw_stringlist_current(macrolist); tstr; tstr = lw_stringlist_next(macrolist)) { preproc_add_macro(pp, tstr); } n = parse_program(pp); preproc_finish(pp); return n; } static void do_error(const char *f, ...) { va_list args; va_start(args, f); fprintf(stderr, "ERROR: "); vfprintf(stderr, f, args); va_end(args); fprintf(stderr, "\n"); exit(1); }