rsalz@uunet.uu.net (Rich Salz) (10/28/89)
Submitted-by: "Fred J. E. Long" <flong@sdsu.edu> Posting-number: Volume 20, Issue 80 Archive-name: multi-include [ I believe this is a solution in search of a problem, but the ongoing discussion in comp.lang.c and comp.lang.c++ indicates that lots of people are interested in something like this. /r$ ] Here is a very simple program I wrote after seeing the recent controversy in comp.lang.c++ over "multiple inclusion". It just puts #if FILENAME != 0 #define FILENAME 0 at the top of each file (if the -i option is specified) and puts #endif /* FILENAME */ at the bottom. The -o option does likewise, but it puts the macros around all the #includes: #include "foobar.h" goes to: #ifndef FOOBAR_H #define FOOBAR_H 1 #include "foobar.h" #endif /* FOOBAR_H */ #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # README # include.1 # include.c # makefile # run_test # test.c # test.h sed 's/^X//' << 'SHAR_EOF' > README XHere is a very simple program I wrote after seeing the recent Xcontroversy in comp.lang.c++ over "multiple inclusion". It just puts X X#if FILENAME != 0 X#define FILENAME 0 X Xat the top of each file (if the -i option is specified) and puts X X#endif /* FILENAME */ X Xat the bottom. The -o option does likewise, but it puts the macros around Xall the #includes: X X#include "foobar.h" X Xgoes to: X X#ifndef FOOBAR_H X#define FOOBAR_H 1 X#include "foobar.h" X#endif /* FOOBAR_H */ X XIt would be a good idea to backup your files before using this program. XHave fun. X X---- XFred J. E. Long Xflong@sdsu.edu, flong@midgard.ucsc.edu X SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > include.1 X.TH INCLUDE 1 "26 October 1989" X.UC 4 X.SH NAME Xinclude \- eases multiple inclusion problems X.SH SYNOPSIS X\fBinclude \-\fR{\fBio\fR}[\fBb\fR] \fIfilename ...\fR X.SH DESCRIPTION X.PP X.I Include Xmodifies the specified files to help eliminate multiple inclusion problems. X.PP XOptions: X.TP 8 X.B \-b XThe named files are backed up. Each backup file will have the X.B .bak Xextension. X.TP 8 X.B \-i XEach file will have X.sp X#if FILENAME != 0 X.br X#define FILENAME 0 X.sp Xas the first two lines of the file, and X.sp X#endif /* FILENAME */ X.sp Xwill be the last line in the file, Xwhere FILENAME is the filename modified to be a legal macro. X.TP 8 X.B \-o XFor any file inclusion X.sp X#include "filename" X.sp Xyou will get X.sp X#ifndef FILENAME X.br X#define FILENAME 1 X.br X#include "filename" X.br X#endif /* FILENAME */ X.sp SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > include.c X/* X * Fred J. E. Long X * X * flong@sdsu.edu X */ X X#include <stdio.h> X X#include <ctype.h> X Xextern char *optarg; Xextern int optind, opterr; X Xint inside = 0, outside = 0, backup = 0; X Xvoid format(name) Xchar *name; X{ X printf("\n%s -{io}[b] files\n\n", name); X printf("\ti\t#ifndef at the top, #endif at the bottom of each file\n"); X printf("\to\tPut #ifndef/#endif around all #include's\n"); X printf("\tb\tBackup all files\n"); X exit(0); X} X Xvoid backup_file(name) Xchar *name; X{ X char tmp[200]; X X sprintf(tmp, "cp %s %s.bak", name, name); X if (system(tmp)) { X printf("\nCould not make backup of %s\n", name); X exit(1); X } X} X Xvoid update_file(tmp, name) Xchar *tmp, *name; X{ X char command[200]; X X sprintf(command, "mv %s %s", tmp, name); X if (system(command)) { X printf("\nCould not update %s\n", name); X exit(1); X } X} X Xchar *is_include(name) Xchar *name; X{ Xstatic char tmp[200]; X int i; X X i = sscanf(name, "#%*[ \t]include%*[ \t]%*1[\"<]%[^\">]%*1[\">]", tmp); X if (i == 1) return(tmp); X else return(0); X} X Xchar *convert(name) Xchar *name; X{ Xstatic char tmp[200], *t; X X for (t = tmp; *name; name++, t++) { X if (isalpha(*name)) { X if (islower(*name)) *t = toupper(*name); X else *t = *name; X } X else *t = '_'; X } X *t = 0; X return(tmp); X} X Xvoid do_for(name) Xchar *name; X{ X char *tmp_name, line[500], *tmp, *mktemp(); X FILE *fi, *fo; X X if (backup) backup_file(name); X X if (!(fi = fopen(name, "r"))) { X printf("\nCould not open %s\n", name); X exit(1); X } X tmp_name = mktemp("/tmp/includeXXXXXX"); X if (!(fo = fopen(tmp_name, "w"))) { X printf("\nCould not open %s\n", tmp_name); X exit(1); X } X if (inside) { X fprintf(fo, "#if %s != 0\n", convert(name)); X fprintf(fo, "#define %s 0\n\n", convert(name)); X } X while (fgets(line, 500, fi)) { X if (!outside || !(tmp = is_include(line))) { X fputs(line, fo); X continue; X } X fprintf(fo, "#ifndef %s\n", convert(tmp)); X fprintf(fo, "#define %s 1\n", convert(tmp)); X fputs(line, fo); X fprintf(fo, "#endif /* %s */\n\n", tmp); X } X if (inside) { X fprintf(fo, "\n#endif /* %s */\n", name); X } X fclose(fi); X fclose(fo); X update_file(tmp_name, name); X} X Xmain(argc, argv) Xint argc; Xchar **argv; X{ X int c; X X while ((c = getopt(argc, argv, "iob")) != EOF) { X switch (c) { X case 'i': inside = 1; break; X case 'o': outside = 1; break; X case 'b': backup = 1; break; X default: format(argv[0]); X } X } X if (inside + outside == 0) { X printf("\nNothing to do; choose -i, -o, or both\n"); X format(argv[0]); X } X for (; optind < argc; optind++) do_for(argv[optind]); X X return(0); X} SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > makefile Xinclude: include.c X cc -o include include.c SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > run_test Xinclude -ib test.h Xinclude -ob test.c Xcc -c test.c SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > test.c X#include "test.h" Xint i = FOOBAR; SHAR_EOF sed 's/^X//' << 'SHAR_EOF' > test.h X#define FOOBAR 2 SHAR_EOF exit -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.