/** * Author: Tom Mutdosch * Makefile generator * * This program automatically generates a Makefile based on the files residing * in the current directory * * $Id: makemake.c,v 1.5 1999/10/20 03:58:40 tommut Exp tommut $ * $Log: makemake.c,v $ * Revision 1.5 1999/10/20 03:58:40 tommut * added support for additional directories in Makefiles * * Revision 1.4 1999/10/10 20:17:50 tommut * *** empty log message *** * * Revision 1.3 1999/10/10 04:33:49 tommut * *** empty log message *** * */ #include #include #include #include #define DEFAULT_DIR "/usr/local/etc/Makefile" int hasExtension( char *str, char *extension ); void readDirectory( char *dir ); int getLine( FILE *fp, char *destination, int maxlen ); void processLine( char *destination, char *line ); int excludeFile( char *fileName ); int createMakefile( ); void printHelp(); char cFiles[256][256], cppFiles[256][256], hFiles[256][256], excludeFiles[256][256], makeLines[256][81], progName[256], directory[256]; int cIndex, cppIndex, hIndex, excludeIndex; int cUpdate = 0, cppUpdate = 0, hUpdate = 0; /** * read the current directory and store all C, cpp, c, and h files in memory */ void readDirectory( char *dirName ) { DIR *dp; struct dirent *dir; char tmpDir[512]; if ( ( strcmp( dirName, "." ) == 0 ) || ( strcmp( dirName, "./" ) == 0 ) ) { strcpy( tmpDir, "" ); } else if ( dirName[strlen(dirName)-1] != '/' ) { sprintf( tmpDir, "%s%c", dirName, '/' ); } else { sprintf( tmpDir, "%s", dirName ); } if ( (dp = opendir( dirName ) ) == NULL ) { fprintf( stderr, "%s: %s", "Can not open current directory.\n", dirName ); return; } while ( (dir = readdir( dp ) ) != NULL ) { if ( dir->d_ino != 0 && !excludeFile( dir->d_name ) ) { if ( hasExtension( dir->d_name, "c" ) ) { sprintf( cFiles[cIndex++], "%s%s", tmpDir, dir->d_name ); } if ( ( hasExtension( dir->d_name, "C" ) ) || ( hasExtension( dir->d_name, "cpp" ) ) ) { sprintf( cppFiles[cppIndex++], "%s%s", tmpDir, dir->d_name ); } if ( hasExtension( dir->d_name, "h" ) ) { sprintf( hFiles[hIndex++], "%s%s", tmpDir, dir->d_name ); } } } } /** * return 1 if str ends with extension, 0 otherwise */ int hasExtension( char *str, char *extension ) { int ret = 0; char *tmp = (char *)strrchr( str, '.' ); if ( tmp != NULL ) { if ( strcmp( tmp + 1, extension ) == 0 ) { ret = 1; } } return ret; } /** * read information from previous Makefile and write out the new one */ int createMakefile( ) { FILE *fp; char line[81]; int num = 0, index = 0, i = 0; /** if no directory is given on command line */ if ( strcmp( directory, "" ) == 0 ) { /** check for Makefile in current directory, first */ if ( (fp = fopen( "Makefile", "r" )) == NULL ) { /** else, use default directory */ if ( (fp = fopen( DEFAULT_DIR, "r" )) == NULL ) { perror( "Could not open Makefile for reading." ); exit( 1 ); } } } else if ( (fp = fopen( directory, "r" )) == NULL ) { perror( "Could not open Makefile for reading." ); exit( 1 ); } memset( line, '\0', 81 ); while ( (num = getLine( fp, line, 81 ) ) != 0 ) { processLine( makeLines[index++], line ); memset( line, '\0', 81 ); } fclose( fp ); /** now write out all of the new data to Makefile */ if ( (fp = fopen( "Makefile", "w" )) == NULL ) { perror( "Could not open Makefile for writing." ); exit( 1 ); } for ( i = 0; i < index; i++ ) { fprintf( fp, "%s", makeLines[i] ); } fclose( fp ); return ( 1 ); } /** * get a line up to maxlen - 1 or a '\n' and place into destination */ int getLine( FILE *fp, char *destination, int maxlen ) { char in; int index = 0; while ( ( index < maxlen - 1 ) && ( (in = fgetc( fp ) ) != EOF ) && in != '\n' ) { destination[index++] = in; } if ( in == '\n' ) { destination[index] = in; index++; } destination[index] = '\0'; return index; } /** * process lines of Makefile and enter new information, such as updated files */ void processLine( char *destination, char *line ) { int i; if ( ( strncmp( line, "CC", 2 ) ) == 0 ) { if ( cppIndex > 0 ) { strcpy( destination, "CC= g++\n" ); } else { strcpy( destination, "CC= gcc\n" ); } } else if ( cUpdate && ( strncmp( line, "CFILES", 6 ) ) == 0 ) { strcpy( destination, "CFILES=" ); for ( i = 0; i < cIndex; i++ ) { sprintf( destination, "%s %s", destination, cFiles[i] ); } strcat( destination, "\n" ); } else if ( cppUpdate && ( ( strncmp( line, "CPPFILES", 8 ) ) == 0 ) ) { strcpy( destination, "CPPFILES=" ); for ( i = 0; i < cppIndex; i++ ) { sprintf( destination, "%s %s", destination, cppFiles[i] ); } strcat( destination, "\n" ); } else if ( hUpdate && ( strncmp( line, "HFILES", 6 ) ) == 0 ) { strcpy( destination, "HFILES=" ); for ( i = 0; i < hIndex; i++ ) { sprintf( destination, "%s %s", destination, hFiles[i] ); } strcat( destination, "\n" ); } else if ( strncmp( line, "PROG", 4 ) == 0 ) { if ( strcmp( progName, "" ) == 0 ) { strcpy( destination, line ); } else { sprintf( destination, "%s %s\n", "PROG=", progName ); } } else { strcpy( destination, line ); } } /** * return 1, if fileName is to be excluded from the Makefile, as per * commandline request */ int excludeFile( char *fileName ) { int i, ret = 0; for ( i = 0; i < excludeIndex; i++ ) { if ( !ret && (strcmp( fileName, excludeFiles[i] ) == 0 ) ) { ret = 1; } } return ret; } /** * parse command line args and set globals accordingly */ int main( int argc, char **argv ) { int i, exclude = 0, dirs = 0, goodArg = 0, dirsCount = 0; char dirNames[256][256]; strcpy( progName, "" ); strcpy( directory, "" ); if ( argc > 1 ) { for ( i = 1; i < argc; i++ ) { if ( exclude ) { strcpy( excludeFiles[excludeIndex++], argv[i] ); } else if ( dirs ) { strcpy( dirNames[dirsCount++], argv[i] ); } else if ( (strcmp( argv[i], "-n" ) == 0 ) ) { if ( i + 1 < argc ) { strcpy( progName, argv[i+1] ); goodArg = 1; } exclude = 0; dirs = 0; } else if ( (strcmp( argv[i], "-m" ) == 0 ) ) { if ( i + 1 < argc ) { strcpy( directory, argv[i+1] ); goodArg = 1; } exclude = 0; dirs = 0; } else if ( (strcmp( argv[i], "-x" ) == 0 ) ) { goodArg = 1; exclude = 1; dirs = 0; } else if ( (strcmp( argv[i], "-d" ) == 0 ) ) { goodArg = 1; exclude = 0; dirs = 1; } else if ( ( strcmp( argv[i], "-h" ) == 0 ) || ( strcmp( argv[i], "--help" ) == 0 ) ) { printHelp(); exit( 0 ); exclude = 0; dirs = 0; } else if ( (strcmp( argv[i], "-uc" ) == 0 ) ) { cUpdate = 1; goodArg = 1; exclude = 0; dirs = 0; } else if ( (strcmp( argv[i], "-uC" ) == 0 ) ) { cppUpdate = 1; goodArg = 1; exclude = 0; dirs = 0; } else if ( (strcmp( argv[i], "-ucpp" ) == 0 ) ) { cppUpdate = 1; goodArg = 1; exclude = 0; dirs = 0; } else if ( (strcmp( argv[i], "-uh" ) == 0 ) ) { hUpdate = 1; goodArg = 1; exclude = 0; dirs = 0; } } if ( !goodArg ) { printHelp(); exit( 0 ); } } /** if no filetypes specified to be updated, default to update all */ if ( cUpdate != 1 && cppUpdate != 1 && hUpdate != 1 ) { cUpdate = 1; cppUpdate = 1; hUpdate = 1; } readDirectory( "." ); for ( i = 0; i < dirsCount; i++ ) { readDirectory( dirNames[i] ); } createMakefile(); return ( 0 ); } void printHelp() { printf( "%s%s%-27s%s%-27s%s%-27s%s%-27s%s%-27s%s%-27s%s%-27s%s", "Usage: makemake [OPTION]...\n", "Create a Makefile based on files in current directory.\n\n", " -n name", "The name of the executable created by the Makefile.\n", " -x file1 [file2] [...]", "Exclude file(s) from being included in the Makefile.\n", " -m makefile", "The Makefile to use, overriding both the default and ", "", " the Makefile in current directory.\n", " -h, --help", "Print help (this screen).\n\n", " -d dir1 [dir2] [...]", "Add files in these directories to the Makefile as\n", "", " well.\n\n" ); printf( "%s%s%-27s%s%-27s%s%-27s%s", "When the following update commands are issued, only those ", "filetypes listed \nwill be updated. The default is all types.\n", " -uc", "Update c files.\n", " -uC, -Ucpp", "Update C or cpp files.\n", " -uh", "Update h files.\n" ); }