/* preprocessor for zc (formerly hcc) , a68k assembler, blink */ #include #define toupper( x ) ( x > 'Z' ? x - ('a'-'A'): x ) char *malloc(); extern char *getenv(); /* flags if 1 then will allow that operation * to be performed on a file */ short dozc,doa68k,doblink,dodebug,debug; short blinkxref,startup,standardblinklib; doexec( x,errmsg,file ) char x[],*errmsg,*file; { if( debug ){ printf("%s\n",x); return(1); } if( ! Execute(x,0L,0L) ){ printf(errmsg,file); quit(); } return(1); } char libdir[32]; /* librarys' dir */ char cmddir[32]; /* zc,a68k,blink 's dir */ char xrefname[128]; /* blink xref file output */ char blinklibs[128]; /* blink lib direc */ char blinkname[128]; /* output file from a68k */ char a68kname[128]; /* output file from zc */ char zcopts[128]; /* zc options for each phase */ char a68kopts[128]; /* a68k options */ char zctemp[128]; /* CCTEMP dir */ char blinkopts[128]; /* blink options */ char buf[256]; /* command line */ char buf2[256]; /* scratch buf */ /* memory allocation/deallocation routines */ struct mem { struct mem *prev; long len; char *memory; } *curmem; char *jmalloc(n) long n; { char *buf; struct mem *memlist; buf=(char *)malloc( n+(long )sizeof(struct mem)); if(!buf){ printf("cc: outofmemory\n"); quit(); } memlist=(struct mem *)buf; memlist->len=n; memlist->memory=buf+sizeof(struct mem); memlist->prev=curmem; curmem=memlist; return(memlist->memory); } quit() { jfree(); exit(0); } jfree(){ struct mem *nxmem; while(curmem != NULL){ nxmem=curmem->prev; free(curmem); /* frees all the memory we so graciously gobbled up */ curmem=nxmem; } }/*end of jfree */ /********************************************************* Handles file list compiles,assembles,links **********************************************************/ /* lists of source file names, as well as type of operation */ struct filenm{ struct filenm *next; struct filenm *prev; short ab; /* abnormal file name */ short zc; /* 1 if .c file */ short a68k; /* 1 if .s file */ char *name; }*files,*curfile; #define copystring( x ) (char *)strcpy( jmalloc( (long )len((char *) x )), x ) /* adds a file to the file list * computes whether an compile and/or assembly will be done * also determines whether this is an abnormal file name. * If so then only a link will be done on the file */ struct filenm *addfile(name) char name[]; { long l; struct filenm *newfile; char *filename; newfile = (struct filenm *)jmalloc(sizeof(struct filenm)); newfile->prev = curfile; newfile->next = NULL; /* last file so far */ if(curfile) curfile->next = newfile; else files = newfile; curfile = newfile; filename = (char *) copystring( (char *)name); curfile->name=filename; /* contains the new filename */ l=len(filename); curfile->ab=0; /* assume it is normal until proven otherwise */ curfile->zc=0; curfile->a68k=0; if(filename[l-2] == '.'){ if(filename[l-1]== 'c'){ curfile->zc = 1; curfile->a68k=1; }else if (filename[l-1] == 'a' || filename[l-1] == 's'){ curfile->a68k=1; }else if(filename[l-1] != 'o') curfile->ab = 1; /* abnormal file name */ }else curfile->ab = 1; /* abnormal file name */ }/* end of addfile */ long len(x) char x[]; { long i; for(i=0; x[i] != 0 ; i++); return(i); } char *tofiletype(nm,buffer,ext1,ext2) char nm[],buffer[],ext1[],ext2; { long l; strcpy(buffer,nm); l=len(buffer); if(l < 2 || ( buffer[l-2] != '.') ){ strcat(buffer,ext1); return(buffer); } if(ext2) buffer[l-1] = ext2; else buffer[l-2] = '\0'; /* must be executable */ return(buffer); }/*end of tofiletype */ #define toassem( x ) tofiletype( x ,a68kname,".s ",'s') #define tolink( x ) tofiletype( x ,blinkname,".o ",'o') #define toexec( x ) tofiletype( x ,blinkname,".lnk ",'\0') doerrors() { FILE *err; int nmerrors; if( (err=fopen("ram:zc.errors","r"))==NULL) return(); nmerrors=0; fscanf(err,"%d",&nmerrors); close(err); if(nmerrors) quit(); return(); /* no errors thank goodness */ } /* this assembles the file */ assemfile(nm,outnm) char nm[],outnm[]; { strcpy(buf,cmddir); strcat(buf,"a68k <* >* "); strcat(buf,a68kopts); strcat(buf,"-o"); strcat(buf,outnm); strcat(buf," "); strcat(buf,nm); Chk_Abort(); doexec(buf,"cc: assemble error: %s\n",nm); }/*end of assemfile*/ /* compiles and/or assembles the files in the file list */ compilefiles(){ struct filenm *file; char nm[]; file=files; while(file){ toassem(file->name);/* use this as the input to a68k * unless updated below */ if(file->zc && dozc ){ strcpy(buf,cmddir); strcat(buf,"zc >* <* -Eram:zc.errors "); strcat(buf,zcopts); strcat(buf," "); if( (file->a68k && doa68k) || file->ab){ strcat(buf," -O"); if(file->a68k && doa68k) strcpy(buf2,zctemp); /* use temp file if doing an assemble */ else buf2[0]='\0'; strcat(buf2,file->name); strcat(buf,toassem(buf2));/* use designated outputfile */ } strcat(buf," "); strcat(buf,file->name); Chk_Abort(); doexec(buf,"cc: compile error: %s\n",file->name);/* start compiler */ doerrors(); /* read error file to see if any errors */ } /* compiled okay */ if(file->a68k && doa68k){ assemfile(a68kname,tolink(file->name)); /* assemble file */ if(file->zc){ /* if was a c file remove .s file */ strcpy(buf,"c:delete >* <* "); strcat(buf,a68kname); Chk_Abort(); doexec(buf,"cc: delete error: %s\n",a68kname); } } file=file->next;/* get next file */ }/* done with this file, compile & assemble next */ }/* done with files */ linkfiles(){ struct filenm *file; char nm[]; if(!doblink || files == NULL ) return();/* don't do anything if not supposed to */ file=files; strcpy(buf,cmddir); strcat(buf,"blink <* >* "); if(startup){ strcat(buf,libdir); strcat(buf,"BothStartup.obj "); } while(file){ strcat(buf,tolink(file->name));/* build linker list */ file = file->next; strcat(buf," "); } strcat(buf," TO "); strcat(buf,toexec(files->name));/* use first file name */ strcat(buf," LIB "); strcat(buf,blinklibs); if(standardblinklib){ strcat(buf,libdir); strcat(buf,"amiga.lib "); } if(!dodebug) strcat(buf," NODEBUG "); if(blinkxref){ strcat(buf," XREF "); strcat(buf,xrefname); } Chk_Abort(); doexec(buf,"cc: linker error:\n",NULL); printf("cc: executable is %s \n",toexec(files->name)); }/* done linking it */ help() { printf("cc: Version 1.0 Preprocessor for \n%s%s%s%s%s%s%s%s%s%s%s%s%s", " cc: Sozobon-C compiler, \n", " as: a68k C.Gibbs Motorola Compatible Assembler, and\n", " blink: Software Distillery Linker \n", " looks for lib:amiga.lib and lib:BothStartup.obj \n", " Syntax:\n", " cc [OPTIONS] \n\n", " Options:\n", " -Dxxxx define xxxx, -Uxxxx undefine xxxx\n", " -C data->chip, -F data->fast\n", " -S don't use startups, -T don't use amiga.lib\n", " -A don't assemble, -c don't link\n", " -Ixxxx include dir, -V printout actions only\n", " -lxxxx use library lib:xxxx.lib\n"); } main(argc,argv) int argc; char *argv[]; { int i, l; char *s; printf("cc: \n"); if(argc < 2 || argv[1][0] == '?'){ help(); exit(0); } startup=standardblinklib=1;/* use BothStartup.obj & amiga.lib */ blinklibs[0]='\0'; /* blink lib direc */ blinkname[0]='\0'; /* output file from a68k */ a68kname[0]='\0'; /* output file from zc */ zcopts[0]='\0'; /* zc options for each phase */ a68kopts[0]='\0'; /* a68k options */ zctemp[0]='\0'; /* CCTEMP dir */ blinkopts[0]='\0'; /* blink options */ buf[0]='\0'; /* command line */ buf2[0]='\0'; /* scratch buf */ dodebug=debug=0; dozc=doa68k=doblink=1;/* will compile,assem,link unless told otherwise*/ curmem=NULL;/* haven't grabbed any memory yet*/ files=NULL; curfile=NULL; blinkxref=0; strcpy(xrefname," "); if( getenv("CCLIB") ){ strcpy(libdir," "); strcat(libdir,getenv("CCLIB")); /* get libdirector */ }else strcpy(libdir," lib:"); /* default directory */ if( ! getenv("CCEXEC") ) strcpy(cmddir,"c:"); else{ strcpy(cmddir,getenv("CCEXEC")); /*dir for zc,a68k,blink */ } if( getenv("CCTEMP") ){ strcpy(zctemp,getenv("CCTEMP")); }else{ printf("cc:Warning, environment variable CCTEMP unset\n Using ram: \n"); strcpy(zctemp,"ram:"); } if( ! getenv("INCLUDE")){ printf("cc: Warning, environment variable INCLUDE unset\n"); }else{ strcpy(a68kopts," -I"); strcat(a68kopts,getenv("INCLUDE") ); } for(i = 1; i < argc; i++){/* parse arguments */ Chk_Abort(); /* Do options */ if(argv[i][0] == '+'){ s = argv[i]; switch(s[1]){ default: printf("cc: No + switches allowed\n"); break; } }else if(argv[i][0] == '-' ){ s = argv[i]; switch(s[1]){ case 'A': case 'a': doblink = doa68k = 0; break; case 'C': /* force data into chip memory */ strcat(zcopts," -C "); break; case 'c': doblink = 0; break; case 'd': case 'D': strcat(zcopts," -D"); strcat(zcopts,&s[2]); break; case 'F': strcat(zcopts," -F "); break; case 'i': case 'I': strcat(zcopts," -I"); strcat(zcopts,&s[2]); break; case 'l': strcat(blinklibs," -l"); strcat(blinklibs,&s[2]); strcat(blinklibs," "); break; case 'T': standardblinklib=0; /* don't use amiga.lib */ break; case 'S': startup = 0;/* don't use BothStartup.obj */ break; case 'u': case 'U': strcat(zcopts," -U"); strcat(zcopts,&s[2]); break; case 'v': case 'V': debug = 1; break; default: printf("bad option: \"%s\"\n", argv[i]); exit(1); break; } }else /* argument wasn't an option so must be a file */ addfile(argv[i]);/* add filename to list of files */ }/* done with parsing arguments */ compilefiles(); /* compile all the files */ linkfiles(); /* link all the files */ quit();/* cleanup mess and go home */ }