home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
useful
/
util
/
edit
/
mg
/
src.lzh
/
tools
/
makemake.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-23
|
11KB
|
427 lines
/*
* 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