This is generate-makefile.m in view mode; [Download] [Up]
/* * generate-makefile * * COPYRIGHT: Hutchison Avenue Software, 1994 [514/499-2067, info@hasc.ca] * * USAGE: * * cc -o generate-makefile generate-makefile.m -all_load -lMiscKit -lNeXT_s * * generate-makefile Class.m OtherClass.m OtherOtherClass.m ... * * CREDITS: * * Author: Darcy Brockbank <samurai@hasc.ca> * Date: Sunday, Dec 4, 1994 * Version: 1.2 */ static const char * version = "generate-makefile (v1.2)"; /* * ADDITIONAL CREDITS: * * This program makes use of the most excellent MiscKit. If you don't * have the MiscKit, you can't compile this program. Luckily for you, * the MiscKit is available for free... contact Don Yactman at * Don_Yacktman@byu.edu for information on the MiscKit. * * Modification History: * * Version 1.0, Dec 4, 1994. samurai@hasc.ca. * Version 1.1, Dec 8, 1994. samurai@hasc.ca. * - added ICONSECTIONS to generated makefile * - changed spacing * - added PSWFILES * Version 1.2, Dec 15, 1994. samurai@hasc.ca. * - checks to see if a class is in there before adding it. * * Description: * * Adds the given Classes to the PB.project in the current directory, and * generates a new makefile. This program is pretty stripped down in * functionality. I can forsee someone adding a few switches to the program, * adding functionality, and this program becoming a nice addition for people * using emacs and other configurable editors... * * Calling this program with no arguments simply transforms the PB.project * file in the current directory into a Makefile. So, if you have to make * custom changes to the PB.project, you can do so then call this * program. * * Please feel free to add functionality to this, and keep me up to date on * new versions! This is only a quick and dirty hack... * * DISCLAIMER * * This software is provided as-is, with no warrantee, or guarantee of fitness * for any particular purpose. You use this software at your own risk, and the * Author(s) may not be held liable for damages resulting from use of this * software. * * COPYING INFORMATION AND GRANTED RIGHTS * * You may freely copy and modify this software as long as you do not modify * any part of this notice, with the following two exceptions: * * (1) If you modify this code, you must add your name and email address * to the modifiction history, together with an explanation of your * modification. * (2) If your modification changes any functionality already present, you * may modify the description to reflect your changes. * */ #import <misckit/MiscString.h> #import <misckit/MiscParseTableFile.h> #import <misckit/MiscDictionary.h> #import <misckit/MiscList.h> #import <errno.h> id read_project(const char *filename) { id string = [[MiscString alloc] initString:filename]; id dictionary = MiscParseTableFile(string); if (!dictionary) { fprintf(stderr,"Problem opening \"%s\", (%s)\n", filename,strerror(errno)); exit(1); } [string free]; return dictionary; } id list_from_array(int count, const char * const *names) { int i; id list = [[List alloc] init]; for (i=0;i<count;i++){ id string = [[MiscString alloc] initString:names[i]]; [list addObject:string]; } return list; } void add_if_absent(id list, id object) { int i, count = [list count]; for(i=0;i<count;i++){ if ([[list objectAt:i] isEqual:object]){ return; } } [list addObject:object]; } void append_uniquely(id list, id files) { int i, count = [files count]; for(i=0;i<count;i++){ add_if_absent(list,[files objectAt:i]); } } void add_to_mfiles(id mfiles, id dictionary) { id name = [[MiscString alloc] initString:"FILESTABLE"]; id section = [dictionary valueForKey:name]; [name setStringValue:"M_FILES"]; section = [section valueForKey:name]; append_uniquely(section,mfiles); [mfiles empty]; } void add_to_classes(id mfiles, id dictionary) { id name = [[MiscString alloc] initString:"FILESTABLE"]; id section = [dictionary valueForKey:name]; [name setStringValue:"CLASSES"]; section = [section valueForKey:name]; append_uniquely(section,mfiles); [mfiles empty]; } void backup(const char *name) { struct stat sb; id backup = [[MiscString alloc] initString:name]; [backup addToEndOfString:"~"]; if (stat(name,&sb)==0){ /* we have something to back up */ if (stat([backup stringValue],&sb)){ /* error finding old backup */ if (errno != ENOENT) { /* backup was there, but something happened */ fprintf(stderr,"Error stat'ing old backup" " \"%s\", (%s)\n", [backup stringValue],strerror(errno)); exit(1); } } else { /* backup was there, so remove it */ if (unlink([backup stringValue])){ fprintf(stderr,"Error unlinking old backup" " \"%s\", (%s)\n", [backup stringValue],strerror(errno)); exit(1); } } /* make the backup */ if (link(name,[backup stringValue])){ fprintf(stderr,"Error creating backup \"%s\", (%s)\n", [backup stringValue],strerror(errno)); exit(1); } else if (unlink(name)){ /* remove the existing file */ fprintf(stderr,"Error deleting old file \"%s\", (%s)\n", name,strerror(errno)); exit(1); } } } void write_project(const char *name, id dictionary) { id string = [[MiscString alloc] initString:name]; backup(name); MiscWriteTableFile(string,dictionary); [string free]; } void write_makefile(const char *name, id dictionary); /* * main */ void main(int argc, char *argv[]) { id dictionary = read_project("PB.project"); if (argc>1){ id mfiles = list_from_array(argc-1,argv+1); add_to_classes(mfiles,dictionary); write_project("PB.project",dictionary); } write_makefile("Makefile",dictionary); } /* * This next chunk handles 80 character wide formatting stuff for the rules. * You call format_setup() then call format_next() every time you want to * write a string, and it takes care of making sure the correct number of * spaces is being added, and that you don't go over the top. */ #define PREFIX " " #define PREFIX_LEN (strlen(PREFIX)) #define MAX_LEN 80 static int _formatLen; void format_setup(FILE *file, int startlen) { _formatLen = startlen; } void format_next(FILE *file, id string) { _formatLen += ([string strlen]) +1 ; if (_formatLen>=MAX_LEN-2){ fprintf(file,"\\\n%s",PREFIX); _formatLen = PREFIX_LEN + ([string strlen]) +1; } fprintf(file,"%s ",[string stringValue]); } /* * All the semi-complicated stuff follows here (it's all for generating the * makefile. I'd normally not put it after main(), but everything before * main() is very simple... */ void write_key(FILE *file, const char *rule, const char *tag, id dict) { id find = [[MiscString alloc] initString:tag]; id val = [dict valueForKey:find]; if (val) fprintf(file,"%s = %s\n",rule,[val stringValue]); [find free]; } void write_blank(FILE *file) { fprintf(file,"\n"); } void write_comment_header(FILE *file) { fprintf(file, "#\n" "# Generated by \"%s\"\n" "#\n" "# Copyright (C) 1994, Hutchison Avenue Software.\n" "#\n" "# \"%s\" is distributable and modifiable, see the source\n" "# for limitations and restrictions.\n" "#\n" "# Contact Darcy Brockbank <samurai@hasc.ca> if you have any problems.\n" "#\n",version,version); } void write_list_formatted(FILE *file, id list) { int i,count = [list count]; for(i=0;i<count;i++){ id string = [list objectAt:i]; format_next(file,string); } fprintf(file,"\n"); } void write_dictionary_formatted(FILE *file, id dict) { id key,val; NXHashState state = [dict initState]; while([dict nextState:&state key:(void **)&key value:(void **)&val]){ format_next(file,key); } fprintf(file,"\n"); } void write_dictionary(FILE *file, const char *rule, const char *tag, id dict) { id find = [[MiscString alloc] initString:tag]; id subdict = [dict valueForKey:find]; if (subdict) { fprintf(file,"%s = ",rule); format_setup(file,strlen(rule)+3); write_dictionary_formatted(file,subdict); } [find free]; } void write_list(FILE *file, const char *rule, const char *tag, id dict) { id find = [[MiscString alloc] initString:tag]; id list = [dict valueForKey:find]; if (list) { fprintf(file,"%s = ",rule); format_setup(file,strlen(rule)+3); write_list_formatted(file,list); } [find free]; } void write_global_resources(FILE *file, const char *rule, id dict) { id find = [[MiscString alloc] initString:"FILESTABLE"]; id filestable = [dict valueForKey:find]; id local, list; const char * resources[] = {"IMAGES", "OTHER_RESOURCES", "INTERFACES", 0}; int i,j,count; fprintf(file,"%s = ",rule); format_setup(file,strlen(rule)+3); [find setStringValue:"LOCALIZABLE_FILES"]; local = [dict valueForKey:find]; for(i=0;resources[i];i++){ [find setStringValue:resources[i]]; list = [filestable valueForKey:find]; for(j=0,count=[list count];j<count;j++){ id current = [list objectAt:j]; if (![local isKey:current]){ format_next(file,current); } } } fprintf(file,"\n"); [find free]; } void write_libs(FILE *file, const char *rule, const char *tag, id dict) { id find = [[MiscString alloc] initString:tag]; id libs = [dict valueForKey:find]; int i,count; fprintf(file,"%s = ",rule); format_setup(file,strlen(rule)+3); for(i=0,count=[libs count];i<count;i++){ id current = [libs objectAt:i]; [current addToFrontOfString:"-l"]; format_next(file,current); } fprintf(file,"\n"); [find free]; } void write_iconsections(FILE *file, const char *rule, id dict) { id find = [[MiscString alloc] initString:"DOCICONFILES"]; id docicons = [dict valueForKey:find]; id appicon; int i,count; fprintf(file,"%s = ",rule); format_setup(file,strlen(rule)+3); [find setStringValue:"APPICON"]; appicon = [dict valueForKey:find]; if (!appicon) { appicon = [[MiscString alloc] initString:"/usr/lib/NextStep/Workspace.app/application.tiff"]; } [appicon addToFrontOfString:"-sectcreate __ICON app "]; format_next(file,appicon); for(i=0,count=[docicons count];i<count;i++){ id current = [docicons objectAt:i]; id extension = [current fileBasename]; [current addToFrontOfString:" "]; [current addToFrontOfString:[extension stringValue]]; [current addToFrontOfString:"-sectcreate __ICON "]; format_next(file,current); [extension free]; } fprintf(file,"\n"); [find free]; } void write_make_info(FILE *file, id dict) { const char * types[] = {"Application", "Bundle", "Palette", "Tool",0}; const char * files[] = {"app.make", "bundle.make", "palette.make", "tool.make",0}; int i; id find = [[MiscString alloc] initString:"PROJECTTYPE"]; id string; /* driverkit should do this differently */ fprintf(file, "%s = %s\n", "MAKEFILEDIR", "/NextDeveloper/Makefiles/app"); string = [dict valueForKey:find]; for(i=0;types[i];i++){ if ([string strcmp:types[i]]==0){ break; } } if (types[i]){ fprintf(file,"%s = %s\n","MAKEFILE",files[i]); } else { fprintf(stderr,"Error... can't find a makefile type\n"); fprintf(stderr,"You should restore the Makefile from the backup.\n"); exit(1); } [find free]; } void write_string(FILE *file, const char *string) { fprintf(file,"%s\n",string); } void write_rule(FILE *file, const char *rule, const char *val) { fprintf(file,"%s = %s\n",rule,val); } void write_makefile(const char *name, id dict) { FILE * file; id find = [[MiscString alloc] initString:"FILESTABLE"]; id filestable = [dict valueForKey:find]; [find free]; backup(name); file = fopen(name,"w"); if (!file) { fprintf(stderr,"Can't open \"%s\" for writing, (%s)\n", name,strerror(errno)); exit(1); } write_comment_header(file); write_blank(file); write_key(file,"NAME","PROJECTNAME",dict); write_blank(file); write_key(file,"PROJECTVERSION","PROJECTVERSION",dict); write_key(file,"LANGUAGE","LANGUAGE",dict); write_key(file,"APPICON","APPICON",dict); write_blank(file); write_list(file,"DOCICONS","DOCICONFILES",dict); write_blank(file); write_dictionary(file,"LOCAL_RESOURCES","LOCALIZABLE_FILES",dict); write_blank(file); write_global_resources(file,"GLOBAL_RESOURCES",dict); write_blank(file); write_list(file,"CLASSES","CLASSES",filestable); write_blank(file); write_list(file,"HFILES","H_FILES",filestable); write_blank(file); write_list(file,"MFILES","M_FILES",filestable); write_blank(file); write_list(file,"CFILES","C_FILES",filestable); write_blank(file); write_list(file,"SUBPROJECTS","SUBPROJECTS",filestable); write_blank(file); write_list(file,"BUNDLES","BUNDLES",filestable); write_blank(file); write_list(file,"PSWFILES","PSW_FILES",filestable); write_blank(file); write_list(file,"OTHERSRCS","OTHER_SOURCES",filestable); write_blank(file); write_blank(file); write_make_info(file,dict); write_key(file,"INSTALLDIR","INSTALLDIR",dict); write_rule(file,"SOURCEMODE","444"); write_blank(file); write_iconsections(file,"ICONSECTIONS",dict); write_blank(file); write_libs(file,"LIBS","OTHER_LIBS",filestable); write_rule(file,"DEBUG_LIBS","$(LIBS)"); write_rule(file,"PROF_LIBS","$(LIBS)"); write_blank(file); write_string(file,"-include Makefile.preamble"); write_string(file,"include $(MAKEFILEDIR)/$(MAKEFILE)"); write_string(file,"-include Makefile.postamble"); write_string(file,"-include Makefile.dependencies"); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.