Back to index

plt-scheme  4.2.1
wbuild.c
Go to the documentation of this file.
00001 /*   wbuild
00002      Copyright (C) 1996  Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>
00003      
00004      This program is free software; you can redistribute it and/or
00005      modify it under the terms of the GNU General Public License
00006      as published by the Free Software Foundation; either version 2
00007      of the License, or (at your option) any later version.
00008      
00009      This program is distributed in the hope that it will be useful,
00010      but WITHOUT ANY WARRANTY; without even the implied warranty of
00011      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012      GNU General Public License for more details.
00013      
00014      You should have received a copy of the GNU General Public License
00015      along with this program; if not, write to the Free Software
00016      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017  */
00018 
00019 #include <config.h>
00020 #include <sys/types.h>
00021 #include <sys/stat.h>
00022 
00023 #include <libit/stat.h>
00024 #include <libit/unistd.h>
00025 #include <libit/string.h>
00026 
00027 #if HAVE_STDARG_H
00028 #include <stdarg.h>
00029 #else
00030 #include <varargs.h>
00031 #endif
00032 
00033 #include <stdio.h>
00034 
00035 #include <libit/getopt.h>
00036 #include <wbuild.h>
00037 #include <wsym.h>
00038 #include <libit/ctype.h>
00039 
00040 #include <libintl.h>
00041 #define _(String) gettext(String)
00042 
00043 #include <libit/malloc.h>
00044 
00045 extern int yyparse();
00046 
00047 /* The global variables are used to hold the program's command line
00048  * arguments (file names), which will be read one by one by the scanner.
00049  */
00050 
00051 extern char *optarg;
00052 extern int optind;
00053 static char **arguments;
00054 static int nrarguments;
00055 extern char *filename;
00056 extern FILE *yyin;
00057 extern int lineno;
00058 int nerrors = 0;
00059 extern time_t filetime;
00060 
00061 void get_filetime(char *filename, time_t *result)
00062 {
00063        struct stat s;
00064        int status;
00065 
00066        *result = (time_t) 0;
00067        status = stat(filename, &s);
00068        if (status == 0)
00069               *result = s.st_mtime;
00070 }
00071 
00072 int yywrap()
00073 {
00074        fclose(yyin);
00075        lineno = 1;
00076        if (optind < nrarguments) {
00077               if (arguments[optind][0] == '-' && arguments[optind][1] == '\0') {
00078                      filename = "<stdin>";
00079                      filetime = 0;
00080                      yyin = stdin;
00081                      optind++;
00082                      return 0;
00083               } else if (! (yyin = fopen(arguments[optind], "r"))) {
00084                      perror(arguments[optind]);
00085                      return 1;
00086               } else {
00087                      filename = arguments[optind];
00088                      get_filetime(filename, &filetime);
00089                      optind++;
00090                      return 0;
00091               }
00092        } else {
00093               return 1;
00094        }
00095 }
00096 
00097 char *build_filename(char *dir, char *name, char *ext)
00098 {
00099        char *tmp;
00100        int dirlen, namelen, extlen;
00101 
00102        dirlen = strlen(dir);
00103        namelen = strlen(name);
00104        extlen = strlen(ext);
00105 
00106        tmp = malloc(dirlen + namelen + extlen + 2);
00107        strcpy(tmp, dir);
00108        tmp[dirlen] = '/';
00109        strcpy(tmp + dirlen + 1, name);
00110        strcpy(tmp + dirlen + namelen + 1, ext);
00111        return tmp;
00112 }
00113 
00114 char *build_guard(char *prefix, char *filename, char *ending)
00115 {
00116        char *tmp, *s;
00117        int prefixlen, filenamelen, endinglen;
00118 
00119        prefixlen = strlen(prefix);
00120        filenamelen = strlen(filename);
00121        endinglen = strlen(ending);
00122 
00123        tmp = malloc(prefixlen + filenamelen + endinglen + 3);
00124        tmp[0] = '_';
00125        strcpy(tmp + 1, prefix);
00126        tmp[prefixlen + 1] = '_';
00127        strcpy(tmp + prefixlen + 2, filename);
00128        strcpy(tmp + prefixlen + filenamelen + 2, ending);
00129 
00130        s = tmp;
00131        while (*s) {
00132               if (ISALPHA(*s)) {
00133                      *s = toupper(*s);
00134               } else if (!isdigit(*s)) {
00135                      *s = '_';
00136               }
00137               s++;
00138        }
00139        return tmp;
00140 }
00141 
00142 void process_file(Class c, char *include_dir, char *c_dir, char *doc_dir,
00143        char *prefix, int lines, int force)
00144 {
00145        char *name, *filename, *guard;
00146        time_t desttime;
00147        Doctype doctype;
00148        FILE *f;
00149 
00150        if (c->filenamepart)
00151               name = get(c->filenamepart);
00152        else
00153               name = get(c->name);
00154 
00155        if (!c->nocode) {
00156               filename = build_filename(include_dir, name, ".h");
00157               get_filetime(filename, &desttime);
00158               if (force || (desttime < c->filetime)) {
00159                      guard = build_guard(prefix, name, "_H");
00160                      f = fopen(filename, "w");
00161                      public_header(f, c, prefix, guard);
00162                      fclose(f);
00163                      free(guard);
00164               }
00165               free(filename);
00166 
00167               filename = build_filename(include_dir, name, "P.h");
00168               get_filetime(filename, &desttime);
00169               if (force || (desttime < c->filetime)) {
00170                      guard = build_guard(prefix, name, "P_H");
00171                      f = fopen(filename, "w");
00172                      generate_private_header(f, c, prefix, guard);
00173                      fclose(f);
00174                      free(guard);
00175               }
00176               free(filename);
00177 
00178               filename = build_filename(c_dir, name, ".c");
00179               get_filetime(filename, &desttime);
00180               if (force || (desttime < c->filetime)) {
00181                      f = fopen(filename, "w");
00182                      generatec(f, c, prefix, lines);
00183                      fclose(f);
00184               }
00185               free(filename);
00186        }
00187 
00188        if (c->nodoc)
00189               return;
00190 
00191        for (doctype = doctypes; doctype; doctype = doctype->next) {
00192               if (doc_dir)
00193                      filename = build_filename(doc_dir, name,
00194                             doctype->tag[t_filename][1]);
00195               else
00196                      filename = build_filename(
00197                             doctype->tag[t_filename][0],
00198                             name, doctype->tag[t_filename][1]);
00199               get_filetime(filename, &desttime);
00200               if (force || (desttime < c->filetime)) {
00201                      f = fopen(filename, "w");
00202                      generate_doc(f, &(doctype->tag), c, doctype->shortdoc);
00203                      fclose(f);
00204               }
00205               free(filename);
00206        }
00207 }
00208 
00209 struct option const longopts[] = {
00210        {"version",          no_argument,         0,     'v'},
00211        {"help",             no_argument,         0,     'h'},
00212        {"no-lines",         no_argument,         0,     'l'},
00213        {"include-prefix",   required_argument,   0,     'p'},
00214        {"only",             required_argument,   0,     'O'},
00215        {"include-dir",             required_argument,   0,     'i'},
00216        {"c-dir",            required_argument,   0,     'c'},
00217        {"doc-dir",          required_argument,   0,     'd'},
00218        {"documentation-dir",       required_argument,   0,     'd'},
00219        {"force",            no_argument,         0,     258},
00220        {"no-init-file",     no_argument,         0,     257},
00221        {0,                  0,                   0,     0}
00222 };
00223 
00224 /* The main program invokes the parser on all command line arguments
00225  * and then calls the generator to create all the C and \TeX\ files
00226  * (unless the parser reported errors).
00227  *
00228  * The intrinsic classes are read from a configuration file, which must
00229  * be present.
00230  */
00231 
00232 int main(int argc, char *argv[])
00233 {
00234        char *include_dir = "../include/Xfwf";
00235        char *c_dir = "../lib";
00236        char *doc_dir = 0;
00237        char *prefix = "Xfwf";
00238        char *only = 0;
00239        int lines = 1;
00240        int help = 0, version = 0;
00241        int force = 0;
00242        int init_file = 1;
00243        int c;
00244        Class class;
00245 
00246        symbol_init();
00247 
00248        arguments = argv;
00249        nrarguments = argc;
00250 
00251        while ((c = getopt_long(argc, argv, "lhvp:O:i:c:d:", longopts,
00252                      /*& optind */ 0)) != -1)
00253               switch (c) {
00254                      case 'l': lines = 0; break;
00255                      case 'h': help = 1; break;
00256                      case 'v': version = 1; break;
00257                      case 'p': prefix = optarg; break;
00258                      case 'O': only = optarg; break;
00259                      case 'i': include_dir = optarg; break;
00260                      case 'c': c_dir = optarg; break;
00261                      case 'd': doc_dir = optarg; break;
00262                      case 257: init_file = 0; break;
00263                      case 258: force = 1; break;
00264                      case '?': help = 1; break;
00265               }
00266        if (help) {
00267               fprintf(stderr, _("wbuild usage:\n"
00268                      "wbuild [options] input-files\n"
00269                      "-v, --version\t\tPrint version and exit\n"
00270                      "-h, --help\t\tPrint this message and exit\n"
00271                      "-l, --no-lines\t\tDon't generate #line directives\n"
00272                      "-p, --include-prefix\tSpecify prefix for generated #include directives\n"
00273                      "-O, --only\t\tSet class to output code for\n"
00274                      "-i, --include-dir\tdirectory for generated include files\n"
00275                      "-c, --c-dir\t\tdirectory for generated c files\n"
00276                      "-d, --doc-dir, --documentation-dir\n"
00277                      "\t\t\tdirectory for generated documentation files\n"
00278                      "    --force\t\tForce regeneration of all files, ignoring timestamps\n"
00279                      "    --no-init-file\tDo not read initialization file\n"
00280                      "\n"
00281                      "Report bugs to free-widgets-bugs@let.rug.nl\n"
00282                      ));
00283               return 0;
00284        } else if (version) {
00285        fprintf (stderr, "wbuild - FWF %s %s\n", "???", "3.2");
00286        fprintf (stderr, _("\
00287 Copyright (C) %s Joel N. Weber II\n\
00288 This is free software; see the source for copying conditions.  There is NO\n\
00289 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
00290 "), "1996");
00291        fprintf (stderr, _("Written by %s\n"),
00292               "Joel N. Weber II <nemo@koa.iolani.honolulu.hi.us>");
00293               return 0;
00294        }
00295        if (init_file) {
00296               yyin = fopen(PKGDATADIR "/init.w", "r");
00297               if (!yyin) {
00298                      perror(PKGDATADIR "/init.w");
00299                      return 1;
00300               }
00301        } else {
00302               yyin = fopen("/dev/null", "r");
00303               if (!yyin) {
00304                      perror("/dev/null");
00305                      return 1;
00306               }
00307               yywrap();
00308        }
00309        lineno = 1;
00310        yyparse();
00311        if (nerrors)
00312               return 1;
00313        nerrors = set_hierarchy();
00314        if (nerrors)
00315               return 1;
00316        for (class = classes; class; class = class->next)
00317               if (!only || (!strcmp(only, get(class->name))))
00318                      process_file(class, include_dir, c_dir, doc_dir,
00319                             prefix, lines, force);
00320        if (nerrors)
00321               return 1;
00322        return 0;
00323 }
00324 
00325 /* The |yywrap| function is called by the scanner when the end of a
00326  * file is reached. The function sets up a new file and returns zero. If
00327  * all files have been read, the function returns 1.
00328  */
00329 
00330 
00331 /* The |err| function is used by the parser to display error messages.
00332  */
00333 
00334 #if !HAVE_STDARG_H
00335 void err(va_alist) va_dcl
00336 {
00337        va_list ap;
00338        int fatal;  
00339        char *format;
00340        va_start(ap);
00341        fatal = va_arg(ap, int);
00342        format = va_arg(ap, char*);
00343 #else /* HAVE_STDARG_H */
00344 #ifdef __STDC__
00345 void err(int fatal, char *format,...)
00346 {
00347        va_list ap;
00348        va_start(ap, format);
00349 #else /* not __STDC__ */
00350 void err(fatal, format) int fatal; char *format;
00351 {
00352        va_list ap;
00353        va_start(ap, format);
00354 #endif /* not __STDC__ */
00355 #endif /* HAVE_STDARG_H */
00356        nerrors++;
00357        (void) fprintf(stderr, "%s:%d: ", filename, lineno);
00358        (void) vfprintf(stderr, format, ap);
00359        if (fatal) exit(1);
00360        va_end(ap);
00361 }