Category : C Source Code
Archive   : MAKER.ZIP
Filename : MAKER.C

 
Output of file : MAKER.C contained in archive : MAKER.ZIP
/*
* ------------------------------------------------------------
* maker102.c, 30Nov86,
* create using Microsoft C, ver 4.0:
* msc maker.c;
link maker.obj \lib\ssetargv.obj;

* create using Turbo C, ver 2.0:
tcc maker wildargs.obj
*
*
* 1) Full support for maker *.c *.asm syntax using ssetargv.obj
* 2) Dual format support - single pass Microsoft make support
* with program target line at bottom of makefile, and
* Unix style format with program target line at top of file.
* 3) Command line options added for -s(ilent, no echo of
* dependencies), -u(nix format, program target line at bottom).
* 4) Defaults added for linkfile, assembler, compiler, and linker.
* Namely, Micosoft's LINK, MASM, and MSC (Ver 4) which are
* hard_coded herein, or via access to environment variables
* MKR_ASM, MKR_CMP, and MKR_LNK if set.
* 5) fixed bug that ignored file not found
*
* Ed Fields
* 8 Proctor Road
* S. Chelmsford, MA 01824
* ------------------------------------------------------------
* maker101.c, This program will create a makefile for you by
* searching the named modukes for 'includes' to determine the
* dependencies. The author of this program is unknown to me.
* Comments, bug fixes and cosmetic changes made by:
*
* Al Bolduc
* 37 Catherine Ave.
* Reading, Mass. 01867
* ------------------------------------------------------------
*/
#include "stdio.h"
#include "dir.h"

#include /* func declarations for string functions */
#include /* func declarations for exit(), getenv() */
#include /* func declarations for cgets() */
#define LINT_ARGS
#define MAXCSTRING 130
/* 127 + 2 + 1 for null */
/* for cgets(), str[0],request count + str[1],fill count + str + null */
#define DWRAP 60
/* wrap output lines at column 60 */
/*
***************************
change thest following #defines for your compiler
*/
#define DFLT_ASSEMBLER "tasm"
#define DFLT_COMPILER "tcc -c -w"
#define DFLT_LINKER "tlink "

int args, filetype, last, line_length, msc_flag, silent;
char ctext[MAXCSTRING], asmtext[MAXCSTRING],
linktext[MAXCSTRING], exetext[MAXCSTRING],
outfil[MAXCSTRING], linkfile[MAXCSTRING], ending[3], *filename;
FILE *fpout;
char *ext_msg = "\n\nFiles must have either .c or .asm extensions\n";
char *bp; /* byte pointer */

int ask(char *, int, char *, ...); /* maker.c */
void follow(char *); /* maker.c */
int get_args(int, char **); /* maker.c */
int get_filename(char *, int); /* maker.c */
int load_dependencies(int, char **); /* maker.c */
int load_linker(int, char **); /* maker.c */
int load_target(int, char **); /* maker.c */
int prefix(char *, char *); /* maker.c */
int remove_spaces(char *); /* maker.c */
void usage(void); /* maker.c */

/*
* maker -- build makefile and link file from module names in
* command line and user responses.
*
* The resultant makefile consists of the following elements:
* exe_file: dependentfiles
* linkername [switches] linkfile
*
* obj_file: dependentfiles #*.c and *.h
* compilername [switches]
*
* obj_file: dependentfiles #*.asm
* assemblername [switches]
*
* The resultant linkfile consists of the following elements:
* objectfile+objectfile
* exefile;
*/
main(argc, argv)
int argc;
char **argv;
{
char *s;

/*
* Initialize the assembler, compiler and linker
* command invocation strings to their default values.
*/
strcpy(asmtext, bp = getenv("MKRASM") ? bp : DFLT_ASSEMBLER);
strcpy(ctext, bp = getenv("MKRCMP") ? bp : DFLT_COMPILER);
strcpy(linktext, bp = getenv("MKRLNK") ? bp : DFLT_LINKER);
strcpy(outfil, "makefile");


if (argc == 1)
usage(), exit(1);
silent = 0, msc_flag = 0;
while (--argc > 0 && (*++argv)[0] == '-') /* K&R, pg. 113 */
{
for (s = argv[0]+1; *s != '\0'; s++)
switch (tolower(*s)) {
case 's':
silent = 1;
break;
case 'm':
msc_flag = 0;
break;
case '?':
printf("usage: maker [-sm] *.c *.asm\n");
printf(" where s is silent, u is Microsoft format,") ;
printf(" default format is unix\n");
exit(1);
break;
} /* switch */
}

/*
* Get makefile name from user and open it.
* uses 'makefile' for default if no response
*/
ask(outfil, 8, "Enter make filename [%s]: ", outfil);
if ((fpout = fopen(outfil, "w")) == NULL)
{
printf("\n\nCannot open %s\n", outfil);
exit(1);
}

if (msc_flag)
{ /* MS make.exe requires .exe.obj to be at end of makefile */
if (load_dependencies(argc, argv) < 0)
exit(1);
if (load_target(argc, argv) < 0)
exit(1);
}
else /* unix format, executable target line at top of file */
{
if (load_target(argc, argv) < 0)
exit(1);
if (load_dependencies(argc, argv) < 0)
exit(1);
}
fclose(fpout);

/* Build the linker input file. */
if (load_linker(argc, argv) < 0)
exit(1);
else
exit(0);
}
/*------------------------------------------*/


/*
* Prompt the user with 'prompt' and return the answer in buffer.
* arg1 and arg2 allows prompt to contain up to 2 format commands
* returns original contents of buffer if user enters only
*/
int ask(buffer, max_count, prompt, arg1, arg2)
char *buffer;
int max_count;
char *prompt, *arg1, *arg2;
{
char temp[MAXCSTRING];

if (max_count == 0)
max_count = MAXCSTRING-3;

if (max_count > MAXCSTRING-3)
max_count = MAXCSTRING-3;
else
max_count += 1;

printf(prompt, arg1, arg2);
*temp = (unsigned char)max_count; /* 256 max */
cgets(temp);
printf("\n");
if (strlen(&temp[2]))
{
strcpy(buffer, &temp[2]);
return 1;
}
return 0;
}
/*------------------------------------------*/


/*
* When called with a module name, 'follow' will search
* the module and the included files for dependencies.
*/
void follow(filename)
char *filename;
{
FILE *fp;
char *result, string[256];

/* Open the file. */
if ((fp = fopen(filename, "r")) == NULL)
{
printf("Warning: %s not found.\n", filename);
return;
}

/* Compute the line length and write out the filename. */
if ((line_length + strlen(filename) + 1) > DWRAP)
{
fprintf(fpout, "\\\n\t");
line_length = 8;
}
fprintf(fpout, "%s ", filename);
line_length = line_length + strlen(filename) + 1;


/*
* Search through the file looking for include files.
* If one is found call 'follow' and when it returns,
* continue the search.
*/
do {
if ((result = fgets(string, 256, fp)) != NULL)
{
remove_spaces(string);
if (filetype == 1) /* 'C' source file. */
{
if (strncmp(string, "#include", 8) == 0)
if (get_filename(string, 8) != 0)
follow(string);
}

else if (filetype == 2) /* 'Assembler' source file. */
{
strlwr(string);
if (strncmp(string, "include", 7) == 0)
if (get_filename(string, 7) != 0)
follow(string);
}
} /* if */
} while (result != NULL);
fclose(fp);

}
/*------------------------------------------*/


/*
* Get the filename from 'string' offset 'n' bytes from the
* beginning. If the filename is valid copy the name back
* onto 'string'. Return the length of filename or zero if
* no good.
*/
int get_filename(string, n)
char *string;
int n;
{
char temp[MAXCSTRING];
int i, j;
int quote_count = 0;
int quit = 0;

for (i = n, j = 0; i < strlen(string); i++)
{
switch (string[i]) {
case ' ':
case '\t':
case '\n':
case 13:
case 12:
break;
case '"':
quote_count++;
break;
case ';':
quit = 1;
break;
case '<':
case '>':
strcpy(string, "");
return(0);
default:
if ((quote_count == 1) && (filetype == 1))
temp[j++] = string[i];
if ((quote_count == 0) && (filetype == 2))
temp[j++] = string[i];
break;
} /* switch */
if (quit)
break;
} /* for */
temp[j] = '\0';
strcpy(string, temp);
return (strlen(string));
}
/*------------------------------------------*/


/*
* Write out each of the object files
* and their dependencies.
*/
load_dependencies(argc, argv)
register int argc;
char **argv;
{
register int i;

for (args = 0; args < argc; args++)
{
filename = argv[args];
fputc('\n', fpout);
if ((filetype = prefix(filename, ":\t")) == 0)
{
printf(ext_msg);
return -1;
}
if (!silent)
printf("\t%s:\n", strlwr(filename));
line_length = 0;
follow(filename);

fputc('\n', fpout);
if (filetype == 1)
fprintf(fpout, "\t%s %s%s\n", ctext, filename, ending);
else
fprintf(fpout, "\t%s %s;\n", asmtext, filename);
fputc('\n', fpout);
}
return 0;
}
/*------------------------------------------*/


/*
*/
int load_linker(argc, argv)
int argc;
char **argv;
{
register int i;

/* Open the linker input file. */
if ((fpout = fopen(linkfile, "w")) == NULL)
{
printf("\n\nCannot open %s\n", linkfile);
return -1;
}
for (line_length = 0, args = 0; args < argc; args++)
{
filename = argv[args];
last = ((argc - 1) == args) ? 1 : 0;
if ((filetype = prefix(filename, "+")) == 0)
{
printf(ext_msg);
fclose(fpout);
return -1;
}
}
fprintf(fpout, "%s;\n", exetext);
fclose(fpout);
return 0;
}
/*------------------------------------------*/


/*
* Get executable name (.exe) from user, use 1st module name
* in command line for default if no response.
* Develop Targetfile line and Link Command line in makefile.
* Get the executable name and write it to the makefile.
*/
load_target(argc, argv)
int argc;
char **argv;
{
int i;

/*
* request .exe file name, show default value derived
* from arg 1 in command line
*/
if (strlen(argv[0]) > 12) /* note argv has been bumped at least once */
{
printf("maker: invalid filename length (path name and/or \
drive letter not supported)\n");
return -1;
}
strncpy(exetext, argv[0], 8);
if (bp = strchr(exetext, '.'))
*bp = '\0'; /* truncate at trailing .ext */

ask(exetext, 8, "Enter .exe name [%s]: ", exetext);
if (bp = strchr(exetext, '.'))
*bp = 0;
line_length = strlen(exetext) + 8;

/* write target file name to Targetfile name line in makefile */
fprintf(fpout, "\n%s.exe:\t", exetext);

/* write target file names out to makefile targetfile line */
for (args = 0; args < argc; args++)
{
filename = argv[args];
if ((filetype = prefix(filename, " ")) == 0)
{
printf(ext_msg);
return -1;
}
}

/*
* Get the linker command and the linker input filename.
* Then write the dependencies after the 'exe' name.
*/
ask(linktext, 127, "Enter linker name and switches [%s]: ", linktext);

/* build default linkfile name from 1st filename on command line */
sprintf(linkfile, "%s.lnk", exetext);
ask(linkfile, 12, "Enter linker output filename [%s]: ", linkfile);
fprintf(fpout, "\n\t%s @%s\n", linktext, linkfile);
return 0;
}
/*------------------------------------------*/


/*
* When called 'string' should contain the source filename
* for an object file. If not return zero. If the compiler
* or assembler strings are null, ask for command.
* Return 1 for a 'c file, 2 for an 'asm' file and zero
* for invalid.
*/
int prefix(string, inter)
char *string, *inter;
{
static int aflag = 0;
static int cflag = 0;

int i, rtnval;
char duplicate[MAXCSTRING], extension[6], name[MAXCSTRING], *bp;

/*
* If 'string' does not have a '.' in it it must
* be invalid. Return zero if no '.'. Then make lower case.
* Break apart the name and extension.
*/
strlwr(string);
strcpy(name, string);
if ((bp = strchr(name, '.')) == '\0')
return 0;
*bp = '\0';
i = strlen(name);
strcpy(extension, bp+1);

/*
* Check for file type. Check the text strings.
* Set the return value.
*/
rtnval = 0;
if (strncmp(extension, "c", 1) == 0)
{
if (!cflag)
{
ask(ctext, 127, "Enter compiler name and switches [%s]: ", ctext);
strcpy(duplicate, ctext);
strlwr(duplicate);
remove_spaces(duplicate);
if (strncmp(duplicate, "msc", 3) == 0)
strcpy(ending, ";");
else
strcpy(ending, "");
cflag = 1;
}
rtnval = 1;
}
else if (strncmp(extension, "asm", 3) == 0)
{
if (!aflag)
{
ask(asmtext, 127, "Enter assembler name and switches [%s]: ",
asmtext);
aflag = 1;
}
rtnval = 2;
}
else
return(rtnval);

/*
* Use the 'inter' string to determine how to
* handle the end of line.
*/
if (strcmp(inter, " ") == 0)
{
if ((line_length + strlen(name) + 5) > DWRAP)
{
fprintf(fpout, "\\\n\t");
line_length = strlen(name) + 5;
}
}
if (strcmp(inter, "+") == 0)
{
if ((line_length + strlen(name) + 5) > DWRAP)
{
fprintf(fpout, "\n");
line_length = strlen(name) + 5;
}
}

/* Output the object file and return 'rtnval'. */
if (last)
strcpy(inter, "\n");
fprintf(fpout, "%s.obj%s", name, inter);
line_length = line_length + i + 5;
return (rtnval);
}
/*------------------------------------------*/


/*
* Remove spaces and tabs from 'string' and return the length.
*/
int remove_spaces(string)
char *string;
{
char temp[255];
int i, j;

for (i = 0; string[i] == ' ' || string[i] == '\t'; ++i)
;
for (j = 0; j < strlen(string); j++, i++)
temp[j] = string[i];
temp[j] = '\0';
strcpy(string, temp);
return (strlen(string));
}
/*------------------------------------------*/


void usage()
{
printf("This program creates a MAKE file and linker file.\n\n");
printf("Command Format: MAKER module.1 [module.2] [module...]\n\n");
printf("module name may include the wildcards: * and ?\n");
printf("module name may only have .c and .asm extensions\n");
printf("modules must reside in the default directory\n");
printf("default assembler, compiler, and linker commands are:\n");
printf("\t%s\n\t%s\n\t%s, respectively.\n", asmtext, ctext, linktext);
printf("Set environment variables MKR_ASM, MKR_CMP, and/or MKR_LNK \
to change defaults,\n");
printf("or make command changes at prompts.\n\n");
printf("Example: MAKER *.c *.asm\n");
}
/*==========================================*/




  3 Responses to “Category : C Source Code
Archive   : MAKER.ZIP
Filename : MAKER.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/