home *** CD-ROM | disk | FTP | other *** search
- /*
- * MakeMake - a program to construct a makefile from C source code
- *
- * Usage: makemake [ -dir ... ] file.c ...
- *
- * MakeMake reads the C source files and outputs on standard out a file
- * of the form:
- * target.o: target.c header file list
- * where the header file list is the transitive closure of all
- * files #included in filex.c (i.e. if filex.c #includes "header.h", and
- * "header.h" #includes "subheader.h", both "header.h" and "subheader.h"
- * appear in the list of header files). MakeMake only examines header
- * files delimited by double quotes ("). It looks for those file in the
- * current directory, and in all directories given as arguments. Include
- * directories are indicated by prepending a "-" to their name. That name
- * is then prepended to the include file name from scanned files, so you'll
- * want to use something like "-/h/ -rexx:". System header files enclosed
- * in angle brackets ("<" and ">") are not examined.
- *
- * Written and placed in the public domain by Tim McGrath 4/2/87
- *
- * modified by Mike Meyer to be usefull in with the BSD-oid makefile
- * construction technic, which replaces the end of an existing makefile
- * with a dependency list. The result is still in the public domain.
- *
- * While I was at it, I deleted the multiple statements per line (so the
- * source-level debugger would be more usefull), and all the tacky, tacky
- * passing around of pointers to int to get a return value. Also fixed
- * the bugs of not printing the first elelement in the array of file
- * names, and other oddities. I also fixed the memory allocator to
- * be less proficient at exercising malloc, and to believe in real
- * limits. The "heap" struct comes from that. My final change was adding
- * -dir to indicate include files. Strange, strange code, this was.
- *
- * Modified again by Lynn Kerby to be useful with the MANX compiler and
- * to use a slightly different convention for command line arguments.
- * to turn on generation of the compilation rule and a more common make
- * file dependency format, use the -M option (upper or lower works fine).
- * Directories must be prefixed with a -i (again, upper or lower case) to
- * be more compatible with C compiler syntax. Also changed it to allow
- * for NON-ANSI compilers with conditional prototypes
- */
- #ifdef LATTICE
- #define _ANSI_C
- #endif
-
- #include <stdio.h>
- #ifdef _ANSI_C
- #include <stdlib.h>
- #endif
- #include <string.h>
-
- #ifdef _ANSI_C
- #define PROTO(x) x
- void main(int, char **) ;
- #else
- #define PROTO(x) ()
- #define NO_PROTOS
- #endif
-
- #define LINEMAX 80
-
- struct heap {
- char **h_names;
- int h_used;
- int h_incr;
- };
- int heap_init PROTO((struct heap * h, int size));
- int heap_add PROTO((struct heap * h, int where, char *name));
-
- #define heap_names(h) ((h) . h_names)
-
- void free_space PROTO((char **dp, int dc));
- char *file_exten PROTO((char *pgm_name, char extension, char *bufout));
- char *base_name PROTO((char *name, char *bufout));
- char *path_name PROTO((char *name, char *bufout));
- void depend_file PROTO((int ct, char **flist, char *pgm_name));
- void start_line PROTO((char *with_name, char *buf));
- int get_dependents PROTO((char *name, struct heap * files,
- struct heap * incs, int cinc));
- int scan_file PROTO((struct heap * h, int list_to_use, FILE * fp,
- struct heap * incs, int cinc));
- FILE *incopen PROTO((char *file, struct heap * incs, int count, char *bufout));
-
- static char RCSid[] = "$Header: makemake.c,v 1.5 90/04/27 15:40:40 lfk Exp $";
- int manx_output = 0;
-
- void
- main(argc, argv)
- char **argv;
- int argc;
- {
- int i, dependent_count, include_count = 0;
- struct heap dependents, includes;
-
- if (!heap_init(&dependents, 10) || !heap_init(&includes, 10)) {
- fprintf(stderr, "No memory\n");
- exit(20);
- }
- for (i = 1; i < argc; i++)
- if (argv[i][0] == '-') {
- switch(argv[i][1]) {
- case 'i':
- case 'I':
- heap_add(&includes, include_count, &argv[i][2]);
- include_count++;
- break;
- case 'm':
- case 'M':
- manx_output++;
- break;
- default:
- fprintf(stderr,"unknown argument %s\n",argv[i]);
- }
- } else {
- dependent_count = get_dependents(argv[i], &dependents, &includes,
- include_count);
- if (dependent_count > 0)
- depend_file(dependent_count, heap_names(dependents), argv[i]);
- free_space(heap_names(dependents), dependent_count);
- }
- exit(0);
- }
-
- void
- free_space(dp, dc)
- /*
- * Purpose: free up list of file names
- * Inputs: dp - points to list of pointers to strings
- * dc - number of pointers in the list
- */
- char **dp;
- int dc;
- {
- while (dc > 0) {
- free(*dp++);
- dc--;
- }
- }
-
- char *
- file_exten(pgm_name, extension, bufout)
- /*
- * Purpose: append new extension onto file name
- * Inputs: pgm_name - pointer to name of file
- * xtension - pointer to new file name extension (2 chars only)
- * Outputs: bufout - points to area for new file name
- * Returns: bufout
- */
- char *pgm_name, extension, *bufout;
- {
- int i = 0;
-
- while (*pgm_name) {
- bufout[i++] = *pgm_name;
- if (*pgm_name++ == '.' && extension) {
- bufout[i++] = extension;
- bufout[i] = '\0';
- return (bufout);
- }
- }
- if (extension) {
- bufout[i++] = '.';
- bufout[i++] = extension;
- }
- bufout[i] = '\0';
- return (bufout);
- }
-
- char *
- base_name(name, bufout)
- /*
- * Purpose: strip any extensions and path off of a file name.
- * Inputs: name - pointer to file name
- * Outputs: bufout - area for new file name
- * Returns: bufout
- */
- char *name, *bufout;
- {
- char *p;
-
- p = strrchr(name, '/');
- if (p == NULL)
- p = strrchr(name, ':');
- if (p == NULL)
- p = name;
- else
- p += 1;
- strcpy(bufout, p);
- p = strrchr(bufout, '.');
- if (p != NULL)
- *p = '\0';
- return bufout;
- }
-
- char *
- path_name(name, bufout)
- /*
- * Purpose: strip the filename off the path
- * Inputs: name - pointer to file name
- * Outputs: bufout - containing the filename portion of the path
- * Returns: bufout
- */
- char *name, *bufout;
- {
- char *p;
-
- strcpy(bufout, name);
- p = strrchr(bufout, '/');
- if (p == NULL)
- p = strrchr(bufout, ':');
- if (p == NULL)
- p = bufout;
- else
- p += 1;
- *p = '\0';
- return bufout;
- }
-
- void
- depend_file(ct, flist, pgm_name)
- /*
- * Purpose: print file name and list of dependents
- * Inputs: ct - number of dependents in the list
- * flist - pointer to a list of pointers to dependent names
- * pgm_name - name of file whose dependents are being printed
- */
- char **flist, *pgm_name;
- int ct;
- {
- int i;
- char buf[LINEMAX], add_name[LINEMAX], pname[LINEMAX];
-
- start_line(file_exten(base_name(pgm_name, add_name), 'o', pname), buf);
- for (i = 0; i < ct; i++) {
- file_exten(flist[i], 0, add_name);
- if (manx_output) {
- if (strlen(buf) + strlen(add_name) + 1 >= LINEMAX - 3) {
- strcat(buf," \\");
- puts(buf);
- strcpy(buf, " ");
- }
- } else {
- if (strlen(buf) + strlen(add_name) + 1 >= LINEMAX - 1) {
- puts(buf);
- start_line(pname, buf);
- }
- }
- strcat(strcat(buf," "),add_name);
- }
- puts(buf);
- if (manx_output) {
- sprintf(buf,"\t$(CC) $(CFLAGS) -o $@ %s$*.c\n",
- path_name(pgm_name,add_name));
- puts(buf);
- }
- }
-
- void
- start_line(with_name, buf)
- /*
- * Purpose: give each line a standard indentation
- * Inputs: with_name - name of root file on each line
- * buf - place to put indented line
- */
- char *with_name, *buf;
- {
- strcpy(buf, with_name);
- strcat(buf, ":");
- }
-
- int
- get_dependents(name, files, incs, cinc)
- /*
- * Purpose: get heap of dependent files for input file
- * Inputs: name - file name to scan for dependents.
- * incs - heap of include directories to look at
- * cinc - cout of above.
- * Outputs: files - heap of dependent file names.
- * Returns: number of files in files.
- */
- char *name;
- struct heap *files, *incs;
- int cinc;
- {
- FILE *fp;
- int result;
-
- if ((fp = fopen(name, "r")) == NULL) {
- fprintf(stderr, "Couldn't open file %s\n", name);
- return 0;
- }
- heap_add(files, 0, name);
- result = scan_file(files, 1, fp, incs, cinc);
- fclose(fp);
- return result;
- }
-
- int
- scan_file(file_name_heap, next_to_use, fp, inc, cinc)
- /*
- * Purpose: search a C source file file #includes, and search the #includes
- * for nested #includes
- * Inputs: fn - name of file to scan
- * next_to_use - last used filename position in file_name_list
- * Outputs: file_name_list - list of included files
- * Returns: new value for last_list_used.
- */
- struct heap *file_name_heap, *inc;
- FILE *fp;
- int next_to_use, cinc;
- {
- FILE *ifp;
- char buf[1024], ifn[LINEMAX];
- int j, k;
-
-
- while (fgets(buf, 1024, fp)) {
- if (strncmp(buf, "#include", 8) == 0) {
- j = 8;
- while (buf[j] == ' ' || buf[j] == '\t')
- j++;
- if (buf[j++] != '"')
- continue;
- k = 0;
- while (buf[j]) {
- if (buf[j] == '"' || buf[j] == '\n')
- break;
- else
- ifn[k++] = buf[j++];
- }
- ifn[k] = '\0';
-
- ifp = incopen(ifn, inc, cinc, buf);
- if (!ifp)
- fprintf(stdout, "Couldn't open include file %s\n", ifn);
- else if (heap_add(file_name_heap, next_to_use, buf))
- next_to_use = scan_file(file_name_heap, next_to_use + 1, ifp,
- inc, cinc);
- fclose(ifp);
- }
- }
- return next_to_use;
- }
-
- FILE *
- incopen(file, incs, count, bufout)
- /*
- * Purpose: Open an include file, figuring out where it is along the way.
- * Inputs: file - name of the file
- * incs - heap of include files to check
- * count - number of include files in the heap
- * Outputs: bufout - name of the file we actually opened.
- * Returns: open file, or NULL if we didn't open the file
- */
- char *file, *bufout;
- struct heap *incs;
- int count;
- {
- FILE *out;
- char *pp;
- register int i = 0;
-
- strcpy(bufout, file);
- out = fopen(bufout, "r");
-
- while (out == NULL && i < count) {
- pp=heap_names(*incs)[i++];
- if (*(pp + strlen(pp) - 1) != '/' && *(pp + strlen(pp) - 1) != ':')
- sprintf(bufout, "%s/%s", pp, file);
- else
- sprintf(bufout, "%s%s", pp, file);
- out = fopen(bufout, "r");
- }
- return out;
- }
-
- heap_init(h, size)
- /*
- * Purpose: Initalize a heap of file names.
- * Inputs: h - the heap
- * size - the initial size and growth increment.
- *
- * Outputs: h, correctly initialized.
- * Returns: TRUE if all went well, FALSE otherwise.
- */
- struct heap *h;
- int size;
- {
- if ((h->h_names = (char **)malloc(size * sizeof(char *))) == NULL)
- return 0;
- h->h_incr = h->h_used = size;
- return 1;
- }
-
- heap_add(h, where, fn)
- /*
- * Purpose: Add a file name to the heap if it's not there already
- * Inputs: h - the heap of names
- * where - where to add the name
- * fn - name of file
- * Returns: 1 if file name added, 0 otherwise
- */
- struct heap *h;
- int where;
- char *fn;
- {
- int i;
- char *p;
-
- for (i = 0; i < where; i++)
- if (!strcmp(h->h_names[i], fn))
- return (0);
- if (where >= h->h_used)
- h->h_names = (char **) realloc(h->h_names,
- (h->h_used += h->h_incr) * sizeof(char *));
- p = strdup(fn);
- if (p == NULL || h->h_names == NULL) {
- fprintf(stderr, "Out of memory");
- exit(20);
- }
- h->h_names[where] = p;
- return (1);
- }
- /*EOF MARKER*/
-
-