home *** CD-ROM | disk | FTP | other *** search
- An Incremental Compilation Package in C by Dave Taylor
-
- /** create.c **/
-
- /** This program creates an executable file from the *.c and *.p source in
- the current directory It uses the same technique that 'make' uses to
- determine if the specified file need be recompiled or not...ie, if the
- date/time of the source file is more recent than the date/time of the
- object file (*.o) then the appropriate compiler is invoked...
-
- Create allows the following arguments:
-
- -g cdb-combatible symbol table and code generated
- -w suppress 'pc' warning messages
- -O turn on the optimizing feature of the C compiler
- -o name use 'name' as the output file
- -l lib include library 'lib'
- -n no execution: display commands to be used only.
- -i ignore bad return codes and go as far as possible
-
- (C) Copyright 1986, 1987 by Dave Taylor
- **/
-
- #include <stdio.h>
- #include <ndir.h> /* directory stuff */
- #include <errno.h> /* system error */
- #include <sys/types.h> /* more types!!! */
- #include <sys/stat.h> /* stat stuff... */
-
- #define MAXLIBS 25 /* max libraries specifiable */
- #define MAXFILES 250 /* max files total in dir */
- #define FNAMELEN 20 /* max file name length */
- #define LONG_SLEN 255 /* long string... */
- #define SLEN 80 /* regular length string... */
-
- #define CC "cc" /* what is the C compiler called? */
- #define PC "pc" /* what is the Pascal comp. called? */
-
- DIR *dirp; /* directory structure... */
- struct direct *dp; /* file entry in directory */
-
- char files[MAXFILES][FNAMELEN]; /* all count in directory */
- int count = 0, /* how many files in directory? */
- ignore = 0, /* -i (ignore errors) flag */
- optimize = 0, /* -O (optimize) flag set */
- libraries = 0, /* counts number of libraries */
- no_execute = 0, /* -n (no execute) flag set */
- compiled = 0, /* count calls to pc & cc */
- cc_debug = 0, /* -g (debug output) flag set */
- no_warn = 0; /* -w (no warning) flag set */
- char outname[SLEN], /* name of executable file */
- libname[MAXLIBS][SLEN]; /* list of library names... */
-
- extern int errno; /* system error number */
- èchar *strcpy(), *strncpy();
- void qsort(), exit();
-
- main(argc, argv)
- int argc;
- char *argv[];
- {
- int strcmp(), i;
-
- parse_arguments(argc, argv); /* starting arguments... */
-
- initially_read_in_directory();
-
- for (i=0; i < count; i++)
- if (suffix(".c", files[i]) || suffix(".p", files[i])) {
- if (newer_than_object(i)) /* aha! Object old */
- compile(files[i]); /* recompile source */
- }
-
- if (compiled || out_of_date_object_file()) /* don't link if nothing has changed! */
- link_load();
- else
- printf("File '%s' is up to date.\n",
- (outname[0] == '\0'? "a.out" : outname));
-
- fini();
- }
-
- parse_arguments(argc, argv)
- int argc;
- char *argv[];
- {
- /** parse the starting arguments setting the flags etc as
- specified...fail from this routine if bad args! **/
-
- int c;
- extern char *optarg;
- extern int optind, opterr;
-
- opterr = 0; /* supress getopt error message! */
- outname[0] = 0; /* initialize to nothing! */
-
- while ((c = getopt(argc, argv, "l:o:Onigw")) != EOF)
- switch (c) {
- case 'g' : cc_debug++; break;
- case 'i' : ignore++; break;
- case 'w' : no_warn++; break;
- case 'l' : strcpy(libname[libraries++], optarg);
- break;
- case 'n' : no_execute++; break;
- case 'O' : optimize++; break;
- case 'o' : strcpy(outname, optarg); break;
- default : exit(fprintf(stderr,
- "Usage: %s -[i|n|O|g|w] [-l library] [-o name]\n", argv[0]));
- }è}
-
- initially_read_in_directory()
- {
- /* initialize the system variables and read in and sort the
- current directory... */
-
- dirp = opendir("."); /* current directory */
-
- while (read_directory(files[count++]) && count < MAXFILES)
- ;
-
- if (count >= MAXFILES) {
- fprintf(stderr,
- "*** Warning: read more files than this program can deal with! ***\n");
- fprintf(stderr,
- "*** Create continuing, but it might be wrong! ***\n");
- }
-
- qsort(files, (unsigned) --count, FNAMELEN, strcmp);
- }
-
- fini()
- {
- /* close everything and let's leave! */
-
- closedir(dirp);
- }
-
- int
- read_directory(buffer)
- char *buffer;
- {
- /** return the next name in the directory...
- returns non-zero iff not out of entries **/
-
- if ((dp = readdir(dirp)) != NULL)
- strncpy(buffer, dp->d_name, FNAMELEN);
-
- return(dp != NULL);
- }
-
- int
- suffix(sf, string)
- char *sf, *string;
- {
- /** returns true iff the suffix of 'string' is 'sf' **/
-
- register int i, j;
-
- i = strlen(string);
- j = strlen(sf);
-
- while (string[i] == sf[j] && j > 0) {
- i--;è j--;
- }
-
- return(sf[0] == string[i] && j == 0 ? 1 : 0 );
- }
-
- int
- newer_than_object(n)
- int n;
- {
- /** returns true iff the source file with index 'n' has a last
- modified time greater than that of the corresponding object
- file... **/
-
- struct stat buffer;
- long source_time;
- char filename[FNAMELEN], *ctime();
-
- if (stat(files[n], &buffer) != 0)
- exit(printf("*** Error: Could not stat %s ***\n", files[n]));
-
- source_time = buffer.st_mtime;
-
- /** look for object file: same name but the last character should
- be an 'o' rather than a 'c' or 'p'... **/
-
- strcpy(filename, files[n]);
- filename[strlen(filename)-1] = 'o';
-
- buffer.st_mtime = 0L;
-
- if (stat(filename, &buffer) != 0)
- if (errno != ENOENT)
- exit(printf("*** Error: Could not stat %s [%d] ***\n",
- filename, errno));
- else
- buffer.st_mtime = 0L;
-
- return(source_time > buffer.st_mtime);
- }
-
- compile(name)
- char *name;
- {
- /** compile the specified source file... **/
-
- char buffer[SLEN];
- register int ret = 0;
-
- if (name[strlen(name)-1] == 'c')
- sprintf(buffer, "%s -c %s%s%s", CC, optimize? "-O ": "",
- cc_debug? "-g ":"", name);
- else
- sprintf(buffer, "%s -c %s%s", PC, no_warn? "-w ":"", name);
- è printf("\t%s\n", buffer);
-
- if (! no_execute) {
- ret = system(buffer);
-
- if (ret != 0) {
- printf("** return code = %d from compile! **\n", ret);
- if (! ignore)
- exit(ret);
- }
- }
-
- compiled++;
- }
-
-
- link_load()
- {
- /** link and load the corresponding object files to create an
- executable file... **/
-
- char buffer[LONG_SLEN], *basename();
- register int i, ret = 0, first_pc = 0;
-
- if (outname[0] != 0)
- sprintf(buffer, "%s -o %s -n", CC, outname);
- else
- sprintf(buffer, "%s -o a.out -n", CC);
-
- for (i=0; i < count; i++)
- if (suffix(".c", files[i]) || suffix(".p", files[i])) {
- strcat(buffer, " ");
- strcat(buffer, files[i]);
- buffer[strlen(buffer)-1] = 'o'; /* make it the object file */
- }
- if (suffix(".p", files[i]) && first_pc++) {
- strcpy(libname[libraries++], "pc");
- }
-
- /** add libraries specified **/
-
- for (i=0; i < libraries; i++)
- sprintf(buffer, "%s -l%s", buffer, libname[i]);
-
- printf("\t%s\n", buffer);
-
- if (! no_execute) {
- ret = system(buffer);
-
- if (ret != 0) {
- printf("** return code = %d from link/load! **\n", ret);
- if (! ignore)
- exit(ret);
- }
- }è}
-
- int
- out_of_date_object_file()
- {
- /** returns true iff executable file is older than any of the
- object files in the directory...if executable name is
- specified, then it checks the date of THAT file... **/
-
- char filename[FNAMELEN];
- struct stat buffer;
- long mod_date;
- register int i;
-
- strcpy(filename, outname[0] != 0? outname: "a.out");
-
- if (stat(filename, &buffer) != 0)
- if (errno != ENOENT)
- exit(printf("*** Could not stat %s [%d] ***\n",
- filename, errno));
- else
- return(1); /* not found: must be out of date!! */
-
- mod_date = buffer.st_mtime;
-
- for (i=0; i < count; i++)
- if (suffix(".c", files[i]) || suffix(".p", files[i])) {
- strcat(filename, files[i]);
- filename[strlen(filename)-1] = 'o'; /* make it an obj file */
-
- stat(filename, &buffer); /* no problem? */
-
- if (buffer.st_mtime > mod_date)
- return(1);
- }
-
- return(0);
- }