koreth@ssyx.ucsc.edu.ucsc.edu (Steven Grimm) (12/20/88)
Submitted-by: uunet!unido!sbsvax!roeder (Edgar Roeder) Posting-number: Volume 1, Issue 80 Archive-name: gstlink [The executable is being posted to the binaries group. -sg] This program was published in the german magazine ST-Computer (3/88 if i remember correctly). It is a new (faster, better) linker for the GST BIN format (used by Lattice-C, Metacomco-Pascal, ...). It supports the same options like the default GST-linker (-with, -prog, -sym, -debug, -list, ...) plus several new ones: -sec = generate seperate TEXT, DATA and BSS segments and leave BSS out of the generated program -nosec = generate the same output as the old linker -mem = specify internal memory size used for linking the program in RAM (yes, therefore it's so fast) -buf = specify buffer size used to read in libraries If you use '-sec' the programs will be much smaller than with the original linker from GST. A friend (of a friend of a ...) hacked this code into the computer so it's poorly documented. But the linker seems to be well debugged, so you should not need to alter the code. The compiled program uses extended argument passing via either PBP/ARGV (as proposed by Allan Pratt) or ARGV with io_vector like the MWC msh. The use is triggered with the presence or absence of PBP in the environment (and of course the right pointer should be there). I have not included the modified startup.asm for Lattice-C (but if there is some interest, ...) . - Edgar --------------------- (cut here) --------------------- /* */ /* */ #include <stdio.h> #include <osbind.h> #include <string.h> #include <ctype.h> #define FMSIZE 64 #define MAX_LEN 32 #define MAX_PDEF 500 #define MAX_NDEF 20 #define BLEN 1024 #define XMAX 10 #define sgn(x) ((x)<0?-1:((x)==0?0:1)) typedef enum direct { data,source,comment,org,section,offset,xdef,xref, define,common,end,eofsy } DIRECT; typedef char ALFA[MAX_LEN]; typedef struct oper { short id; char op; } OPER; typedef struct symbol { short length; DIRECT directive; char string[81]; long longword; short id; char trunc_rule; unsigned char data_byte; short n_xref; OPER xref_oper[XMAX]; } SYMBOL; typedef struct mod_item { struct mod_item *mod_next; char mod_name[2]; } MOD_ITEM; typedef struct section { struct section *sec_next; short sec_id; char *sec_start; long sec_length; long sec_oldlen; long sec_fxref; long sec_xptr; MOD_ITEM *sec_module; char sec_name[MAX_LEN]; } SECTION; typedef struct xsym { SECTION *xsy_sect; MOD_ITEM *xsy_mod; long xsy_value; short xsy_defd; struct xsym *xsy_left; struct xsym *xsy_right; char xsy_name[MAX_LEN]; } XSYMBOL; typedef struct xoper { char xop_oper; char xop_optyp; union { SECTION *xop_sec; XSYMBOL *xop_sym; } xop_ptr; } XOPER; typedef struct xref { struct xref *xref_next; long xref_pos; long xref_abs; short xref_trunc; short xref_ops; struct xoper xref_oper[XMAX]; } XREF; extern void app_xsy(XSYMBOL**,XSYMBOL*); extern XSYMBOL* src_xsy(XSYMBOL*,char*); extern void app_sec(SECTION**,SECTION*); extern SECTION* src_sec(SECTION*,char*); extern int read_b(); extern void printsy(); extern void nxsy(); extern void move_up(SECTION*); extern SECTION* def_section(SECTION*,char*,short); extern long calc_xsy(XSYMBOL*); SYMBOL sy; char message[]="68000 GST-Format-Linker Version 2.4 / 8.1.1988\n\n"; char module_name[80]; ALFA *pdef_name; ALFA *ndef_name; char input_name[FMSIZE],file_name[FMSIZE],control_name[FMSIZE]; char listing_name[FMSIZE],program_name[FMSIZE]; short control_flag,listing_flag,program_flag,debug_flag,symbol_flag; short spar_flag; char *membot,*memtop,*memstart,*memend,*altstart,*code_ptr,*neustart; char *altxref,*debug_start,*debug_end; long mem_size,buf_size; unsigned char *module_buffer,*module_end,*module_ptr,*module_top,*module_max; SECTION *curr_sec,*sec_liste,*moved_sec; SECTION **sec_lptr=&sec_liste; MOD_ITEM *mod_liste,*curr_mod; XSYMBOL *xsy_liste; XREF *xref_liste; FILE *list_file; int undefd_sym,double_sym,range_err; short header[14]={0x601a,0,0,0,0,0,0,0,0,0,0,0,0,0}; char *errmsg[] = { "Out of memory", "Program memory too small", "Error in binary file", "Too many operands in XREF", "Illegal section id", "Illegal symbol id", "ORG encountered", "Should not occur", "Word or longword at odd address", "Cannot write file correctly" }; void halt(n) int n; { printf("Error %2d: %s.\n",n,errmsg[n]); printf("Press any key to continue\n"); gemdos(1); exit(1); } int strnicmp(x,y,n) register char *x,*y; register unsigned int n; { if (n<1) return(0); while(toupper(*x)==toupper(*y) && *x && *y && --n) { x++; y++; } return((int)(toupper(*x)-toupper(*y))); } void statistic() { SECTION *s; fprintf(list_file,"\n---------------------------\n"); fprintf(list_file,"SECTION START LENGTH\n"); fprintf(list_file,"---------------------------\n"); for (s=sec_liste;s!=NULL;s=s->sec_next) fprintf(list_file, "%-9s %8X %8X\n",s->sec_name,s->sec_start-membot,s->sec_length); fprintf(list_file,"---------------------------\n"); } MOD_ITEM *app_mod(mod_liste,name) MOD_ITEM **mod_liste; char *name; { MOD_ITEM *new; new = (MOD_ITEM*)malloc(sizeof(MOD_ITEM)+strlen(name)); if (new==NULL) halt(0); strcpy(new->mod_name,name); new->mod_next = *mod_liste; *mod_liste = new; return(new); } void app_xsy(xsy_liste,xsy_neu) XSYMBOL **xsy_liste,*xsy_neu; { int c; if (*xsy_liste==NULL) { *xsy_liste=xsy_neu; xsy_neu->xsy_left=xsy_neu->xsy_right=NULL; } else if ((c=stricmp(xsy_neu->xsy_name,(*xsy_liste)->xsy_name))<0) app_xsy(&(*xsy_liste)->xsy_left,xsy_neu); else app_xsy(&(*xsy_liste)->xsy_right,xsy_neu); } XSYMBOL *src_xsy(xsy_liste,name) XSYMBOL *xsy_liste; char *name; { int c; if (xsy_liste==NULL) return(NULL); if ((c=stricmp(name,xsy_liste->xsy_name))==0) return(xsy_liste); if (c<0) return(src_xsy(xsy_liste->xsy_left,name)); else return(src_xsy(xsy_liste->xsy_right,name)); return(NULL); } long calc_xsy(s) XSYMBOL *s; { long value; value=s->xsy_value; if (s->xsy_sect!=NULL) value+=s->xsy_sect->sec_start-membot; return(value); } void debug_table(x) XSYMBOL *x; { register char *p; register short i; if (x!=NULL) { if (code_ptr+14>=memtop) halt(1); debug_table(x->xsy_left); p=x->xsy_name; for (i=8;i--;) { *code_ptr++=*p; if (*p) p++; } if (x->xsy_sect!=NULL) *((short*)code_ptr)=0xA200; else *((short*)code_ptr)=0xA000; code_ptr+=2; *((long*)code_ptr)=calc_xsy(x); code_ptr+=4; debug_table(x->xsy_right); } } void list_xsy(xsy_liste,u_flag) XSYMBOL *xsy_liste; int u_flag; { if (xsy_liste!=NULL) { list_xsy(xsy_liste->xsy_left,u_flag); if (u_flag) { if (!(xsy_liste->xsy_defd&1)) { fprintf(list_file,"Undefined Symbol: '%s'\n",xsy_liste->xsy_name); undefd_sym++; } } else { if (xsy_liste->xsy_defd&1) { fprintf(list_file, "%-20s %08X%c",xsy_liste->xsy_name,calc_xsy(xsy_liste), xsy_liste->xsy_defd&2?' ':'*'); if (xsy_liste->xsy_sect!=NULL) fprintf(list_file," %15s",xsy_liste->xsy_sect->sec_name); else fprintf(list_file," %20s"," "); if (xsy_liste->xsy_mod!=NULL) fprintf(list_file," %15s",xsy_liste->xsy_mod->mod_name); fprintf(list_file,"\n"); } else fprintf(list_file,"%-20s undefined\n",xsy_liste->xsy_name); } list_xsy(xsy_liste->xsy_right,u_flag); } } void app_sec(sec_liste,sec_neu) SECTION **sec_liste,*sec_neu; { if (*sec_liste==NULL) { *sec_liste=sec_neu; sec_neu->sec_next=NULL; } else if (sec_neu->sec_id<=(*sec_liste)->sec_id) app_sec(&(*sec_liste)->sec_next,sec_neu); else { sec_neu->sec_next=*sec_liste; *sec_liste=sec_neu; } } SECTION* src_sec(sec_liste,name) SECTION *sec_liste; char *name; { while(sec_liste!=NULL) { if (stricmp(sec_liste->sec_name,name)==0) return(sec_liste); sec_liste=sec_liste->sec_next; } return(NULL); } unsigned char inp_buf[BLEN],*buf_ptr,*buf_end; int inp_hnd; int read_b() { if (buf_end-inp_buf<BLEN) return(-1); buf_end=inp_buf+Fread(inp_hnd,BLEN,inp_buf); buf_ptr=inp_buf; return(buf_ptr<buf_end ? (int)*buf_ptr++ : -1); } int get_drct() { return(buf_ptr<buf_end ? (int)*buf_ptr++ : read_b()); } int get_byte() { return(module_ptr<module_end ? (int)*module_ptr++ : get_drct()); } void nxsy() { int c; if ((c=get_byte())==0xFB) { register char *p; register int i; switch(get_byte()) { case -1 : sy.directive=eofsy; sy.length=0; break; case 0x01 : sy.directive=source; sy.length=0; p=sy.string; for(i=get_byte();i--;) *p++=get_byte(); *p='\0'; break; case 0x02 : sy.directive=comment; sy.length=0; p=sy.string; for(i=get_byte();i--;) *p++=get_byte(); *p='\0'; break; case 0x03 : sy.directive=org; sy.length=0; sy.longword=(get_byte()<<24)+(get_byte()<<16)+ (get_byte()<<8)+(get_byte()); break; case 0x04 : sy.directive=section; sy.length=0; sy.id=(get_byte()<<8)+(get_byte()); break; case 0x05 : sy.directive=offset; sy.length=0; sy.longword=(get_byte()<<24)+(get_byte()<<16)+ (get_byte()<<8)+(get_byte()); break; case 0x06 : sy.directive=xdef; sy.length=0; p=sy.string; for(i=get_byte();i--;) *p++=get_byte(); *p='\0'; sy.longword=(get_byte()<<24)+(get_byte()<<16)+ (get_byte()<<8)+(get_byte()); sy.id=(get_byte()<<8)+(get_byte()); break; case 0x07 : sy.directive=xref; sy.longword=(get_byte()<<24)+(get_byte()<<16)+ (get_byte()<<8)+(get_byte()); sy.trunc_rule=get_byte(); sy.length=sy.trunc_rule&7; for (i=0;(c=get_byte())!=0xFB && i<XMAX;i++) { if (c!='+' && c!='-') { printf("Illegal XREF Operator : %c\n",c); halt(2); } sy.xref_oper[i].op=c; sy.xref_oper[i].id=(get_byte()<<8)+(get_byte()); } if (c!=0xFB) halt(3); sy.n_xref=i; break; case 0x10 : sy.directive=define; sy.length=0; sy.id=(get_byte()<<8)+(get_byte()); p=sy.string; for (i=get_byte();i--;) *p++=get_byte(); *p='\0'; break; case 0x12 : sy.directive=common; sy.length=0; sy.id=(get_byte()<<8)+(get_byte()); break; case 0x13 : sy.directive=end; sy.length=0; break; case 0xFB : sy.directive=data; sy.length=1; sy.data_byte=0xFB; break; default : printf("Illegal Directive\n"); halt(2); break; } } else { if (c==-1) { sy.directive=eofsy; sy.length=0; } else { sy.directive=data; sy.data_byte=c; sy.length=1; } } } void move_up(s) SECTION *s; { if (memend!=memtop) halt(-1); moved_sec=s; if (s!=NULL) if (s->sec_start!=NULL) { altstart=memstart; memstart=s->sec_start; memend=memtop-(altstart-memstart); if (altstart>memstart) movmem(memstart,memend,altstart-memstart); } else moved_sec=NULL; } void comment_dir() { fprintf(list_file,"COMMENT: %s\n",sy.string); nxsy(); } void xdef_dir(body_flag) int body_flag; { XSYMBOL *s; if ((s=src_xsy(xsy_liste,sy.string))==NULL) { if ((s=(XSYMBOL*)malloc(sizeof(XSYMBOL)))==NULL) halt(0); strupr(sy.string); strncpy(s->xsy_name,sy.string,MAX_LEN-1); s->xsy_defd=0; s->xsy_mod=NULL; app_xsy(&xsy_liste,s); } if (s->xsy_defd&1) { fprintf(list_file,"Double defined Symbol: %s\n",sy.string); double_sym++; } else { if (sy.id) { if (sy.id>0 || -sy.id>MAX_NDEF) halt(4); if ((s->xsy_sect=src_sec(sec_liste,ndef_name[-sy.id]))==NULL) { if (body_flag) halt(2); s->xsy_sect=def_section(sec_liste,ndef_name[-sy.id],sy.id); } } else s->xsy_sect=NULL; s->xsy_value=sy.longword; if (s->xsy_sect!=NULL) s->xsy_value += s->xsy_sect->sec_oldlen; s->xsy_defd |= 1; s->xsy_mod = curr_mod; } nxsy(); } void define_dir() { strupr(sy.string); if (sy.id>0) { if (sy.id>MAX_PDEF) halt(4); strncpy(pdef_name[sy.id],sy.string,MAX_LEN-1); } else { if (-sy.id>MAX_NDEF) halt(5); strncpy(ndef_name[-sy.id],sy.string,MAX_LEN-1); } nxsy(); } SECTION *def_section(sec_liste,name,id) SECTION *sec_liste; char *name; short id; { SECTION *sec; if (NULL==(sec=(SECTION*)malloc(sizeof(SECTION)))) halt(0); strupr(name); strncpy(sec->sec_name,name,MAX_LEN-1); sec->sec_start = NULL; sec->sec_length = 0; sec->sec_oldlen = 0; sec->sec_id = -1; sec->sec_module = curr_mod; if (!stricmp(sec->sec_name,"DATA")) sec->sec_id=-2; if (!stricmp(sec->sec_name,"BSS")) sec->sec_id=-3; if (!stricmp(sec->sec_name,"UDATA")) sec->sec_id=-3; sec->sec_fxref = NULL; sec->sec_xptr = (long)&sec->sec_fxref; app_sec(sec_lptr,sec); return(sec); } void sec_com_dir() { if (sy.id>=0 || -sy.id>= MAX_NDEF) halt(4); if (NULL==(curr_sec=src_sec(sec_liste,ndef_name[-sy.id]))) { curr_sec=def_section(sec_liste,ndef_name[-sy.id],sy.id); move_up(curr_sec->sec_next); curr_sec->sec_start=memstart; } else { move_up(curr_sec->sec_next); if (curr_sec->sec_start==NULL) curr_sec->sec_start=memstart; } } void section_dir() { sec_com_dir(); code_ptr=neustart=memstart; nxsy(); } void org_dir() { halt(6); nxsy(); } void common_dir() { sec_com_dir(); neustart=memstart; code_ptr=curr_sec->sec_start; nxsy(); } void data_dir() { if (code_ptr>=memend) halt(1); *code_ptr++=sy.data_byte; nxsy(); } void offset_dir() { if (code_ptr>neustart) neustart=code_ptr; code_ptr=memstart+sy.longword; if (code_ptr>neustart) neustart=code_ptr; nxsy(); } void xref_dir() { XREF *x; XSYMBOL *xsy; SECTION *sec; short i,xid; if ((x=(XREF*)malloc(sizeof(XREF)+(sy.n_xref-XMAX)*sizeof(XOPER)))==NULL) halt(0); if (curr_sec==NULL) halt(2); x->xref_pos = code_ptr-curr_sec->sec_start; x->xref_abs = sy.longword; x->xref_ops = sy.n_xref; x->xref_trunc = sy.trunc_rule; x->xref_next = NULL; for (i=0;i<sy.n_xref;i++) { x->xref_oper[i].xop_oper=sy.xref_oper[i].op; xid=sy.xref_oper[i].id; switch(x->xref_oper[i].xop_optyp=sgn(xid)) { case -1 : if (-xid>MAX_NDEF) halt(4); if ((sec=src_sec(sec_liste,ndef_name[-xid]))==NULL) sec=def_section(sec_liste,ndef_name[-xid],xid); x->xref_oper[i].xop_ptr.xop_sec=sec; if (x->xref_oper[i].xop_oper=='+') x->xref_abs += sec->sec_oldlen; else x->xref_abs -= sec->sec_oldlen; break; case 0 : break; case 1 : if ((xsy=src_xsy(xsy_liste,pdef_name[xid]))==NULL) { if ((xsy=(XSYMBOL*)malloc(sizeof(XSYMBOL)))==NULL) halt(0); strncpy(xsy->xsy_name,pdef_name[xid],MAX_LEN-1); xsy->xsy_defd=0; xsy->xsy_mod=NULL; app_xsy(&xsy_liste,xsy); } xsy->xsy_defd |= 2; x->xref_oper[i].xop_ptr.xop_sym=xsy; break; } } *((XREF**)curr_sec->sec_xptr)=x; curr_sec->sec_xptr=(long)&x->xref_next; code_ptr += sy.trunc_rule & 7; if (code_ptr>=memend) halt(1); nxsy(); } void header_command() { int in_header_com=1; while (in_header_com) switch (sy.directive) { case comment : comment_dir();break; case xdef : xdef_dir(0);break; case define : define_dir();break; default : in_header_com=0;break; } } void section_command() { switch (sy.directive) { case section : section_dir();break; case org : org_dir();break; case common : common_dir();break; default : halt(2);break; } } void body() { while (sy.directive==data || sy.directive==offset || sy.directive==xdef || sy.directive==xref || sy.directive==define || sy.directive ==comment) { switch(sy.directive) { case data : data_dir();break; case offset : offset_dir();break; case xdef : xdef_dir(1);break; case xref : xref_dir();break; case define : define_dir();break; case comment : comment_dir();break; default : halt(2);break; } } } void chunk() { SECTION *s; while (sy.directive==xdef || sy.directive==comment || sy.directive==define) header_command(); if (sy.directive==section || sy.directive==org || sy.directive==common) { section_command(); body(); if (((long)code_ptr&1) && code_ptr>=neustart) { if (code_ptr>=memend) halt(1); *code_ptr++='\0'; } if (code_ptr>neustart) neustart=code_ptr; curr_sec->sec_length+=neustart-memstart; if (altstart!=NULL) { if (altstart>memstart) movmem(memend,neustart,altstart-memstart); for(s=moved_sec;s!=NULL;s=s->sec_next) if (s->sec_start!=NULL) s->sec_start += neustart-memstart; memend=memtop; neustart+=altstart-memstart; altstart=NULL; } memstart=neustart; } } void module() { SECTION *sec; short i; if (sy.directive!=source) halt(2); curr_mod=app_mod(&mod_liste,sy.string); strcpy(module_name,sy.string); nxsy(); while (sy.directive==xdef || sy.directive==comment || sy.directive==define || sy.directive==section || sy.directive==org || sy.directive==common) chunk(); if (sy.directive!=end) halt(2); if (listing_flag) fprintf(list_file,"%-12.12s:",module_name); i=0; for (sec=sec_liste;sec!=NULL;sec=sec->sec_next) { if (listing_flag) { if (i++>3) { fprintf(list_file,"\n"); i=0; } fprintf(list_file," %8.8s=%08X", sec->sec_name,sec->sec_length-sec->sec_oldlen); } sec->sec_oldlen=sec->sec_length; } if (listing_flag) fprintf(list_file,"\n"); strcpy(module_name,"NO MODULE"); nxsy(); } void calc_xref(x,c,modname) XREF *x; char *c,*modname; { short i; long value; value = x->xref_abs; c += x->xref_pos; /* printf("XREF at %8X %8X",c-membot,value); */ for (i=0;i<x->xref_ops;i++) { /* printf("%c",x->xref_oper[i].xop_oper); */ switch (x->xref_oper[i].xop_optyp) { case -1 : if (x->xref_oper[i].xop_oper=='+') value+=x->xref_oper[i].xop_ptr.xop_sec->sec_start -membot; else value-=x->xref_oper[i].xop_ptr.xop_sec->sec_start -membot; /* printf("%s/%x",x->xref_oper[i].xop_ptr.xop_sec->sec_name, x->xref_oper[i].xop_ptr.xop_sec->sec_start); */ break; case 0 : if (x->xref_oper[i].xop_oper=='+') value+=c-membot; else value-=c-membot; printf("&"); break; case 1 : if (x->xref_oper[i].xop_oper=='+') value+=calc_xsy(x->xref_oper[i].xop_ptr.xop_sym); else value-=calc_xsy(x->xref_oper[i].xop_ptr.xop_sym); /* printf("%s"/%x",x->xref_oper[i].xop_ptr.xop_sym->xsy_name, calc_xsy(x->xref_oper[i].xop_ptr.xop_sym)); */ break; } /* printf("\n"); */ } if (c<membot || c>memstart) halt(2); if (x->xref_trunc & 32) value -=c-membot; switch(x->xref_trunc & 7) { case 4 : if (((long)c)&1) halt(1); *((long*)c)=value; break; case 2 : if (((long)c)&1) halt(1); *((short*)c)=value; if (x->xref_trunc & 8) { if (value<-32768L || value>32767L) { range_err++; printf("XREF.W-value out of range in module '%s'\n", modname); } } else { if (value>65535L) { range_err++; printf("XREF.UW-value out of range in module '%s'\n", modname); } } break; case 1 : *c=value; if (x->xref_trunc & 8) { if (value<-128L || value>128L) { range_err++; printf("XREF.B-value out of range in module '%s'\n", modname); } } else { if (value>255L) { range_err++; printf("XREF.UB-value out of range in module '%s'\n", modname); } } break; default: halt(2); } if (x->xref_trunc & 64) { if (altxref==NULL) { if (code_ptr>=memtop-4) halt(1); altxref=c; *((long*)code_ptr)=c-membot; code_ptr+=4; } else { while (c-altxref>254) { altxref+=254; if (code_ptr>=memtop) halt(1); *code_ptr++='\001'; } if (code_ptr>=memtop) halt(1); *code_ptr++=c-altxref; altxref=c; } } } void all_xrefs(sec_liste) SECTION *sec_liste; { XREF *x; while (sec_liste!=NULL) { x=(XREF*)sec_liste->sec_fxref; while (x!=NULL) { calc_xref(x,sec_liste->sec_start,sec_liste->sec_module->mod_name); x=x->xref_next; } sec_liste=sec_liste->sec_next; } if (altxref==NULL) { if (code_ptr>=memtop-8) halt(1); *((long*)code_ptr)=0; code_ptr+=4; *((long*)code_ptr)=0; code_ptr+=4; } else { if (code_ptr>=memtop) halt(1); *code_ptr++='\0'; } } void init_mem() { pdef_name=(ALFA*)malloc(MAX_PDEF*sizeof(ALFA)); ndef_name=(ALFA*)malloc(MAX_NDEF*sizeof(ALFA)); membot=(char*)malloc(mem_size); module_buffer=(char*)malloc(buf_size); if (membot==NULL || module_buffer==NULL || ndef_name==NULL || pdef_name==NULL) halt(0); memtop=membot+mem_size; memstart=membot; memend=memtop; altstart=NULL; module_top=module_buffer+buf_size; module_max=module_ptr=module_end=module_buffer; } void make_ext(make_name,name,ext) char *make_name,*name,*ext; { char oldtext[FMSIZE]; stcgfe(oldtext,name); if (!*oldtext) strmfe(make_name,name,ext); else strcpy(make_name,name); } void command_line(argc,argv) int argc; char *argv[]; { int i=2; int x; if (argc<2) { printf("No Filename specified\n"); exit(1); } strcpy(file_name,argv[1]); strmfe(input_name,file_name,"BIN"); strmfe(listing_name,file_name,"MAP"); strmfe(control_name,file_name,"LNK"); strmfe(program_name,file_name,"PRG"); listing_flag=0; control_flag=0; program_flag=1; debug_flag=0; symbol_flag=0; spar_flag=0; i=2; if (argc>i) if (*argv[i]!='-') { make_ext(control_name,argv[i++],"LNK"); control_flag=1; } if (argc>i) if (*argv[i]!='-') { make_ext(listing_name,argv[i++],"MAP"); listing_flag=1; } if (argc>i) if (*argv[i]!='-') make_ext(program_name,argv[i++],"PRG"); for (;i<argc;i++) { if (!stricmp(argv[i],"-NOLIST")) {listing_flag=0; continue;} if (!stricmp(argv[i],"-NODEBUG")) {debug_flag=0; continue;} if (!stricmp(argv[i],"-NOPROG")) {program_flag=0; continue;} if (!stricmp(argv[i],"-DEBUG")) {debug_flag=1; continue;} if (!stricmp(argv[i],"-SYM")) {symbol_flag=1; continue;} if (!stricmp(argv[i],"-NOSYM")) {symbol_flag=0; continue;} if (!stricmp(argv[i],"-SEC")) {spar_flag=1; continue;} if (!stricmp(argv[i],"-NOSEC")) {spar_flag=0; continue;} if (!stricmp(argv[i],"-WITH")) { if (i+1<argc) if (*argv[i+1]!='-') make_ext(control_name,argv[++i],"LNK"); control_flag=1; continue; } if (!stricmp(argv[i],"-LIST")) { if (i+1<argc) if (*argv[i+1]!='-') make_ext(listing_name,argv[++i],"LST"); listing_flag=1; continue; } if (!stricmp(argv[i],"-PROG")) { if (i+1<argc) if (*argv[i+1]!='-') make_ext(program_name,argv[++i],"PRG"); program_flag=1; continue; } if (!stricmp(argv[i],"-MEM")) { if (i+1<argc) if (*argv[i+1]!='-') { x=atoi(argv[++i]); if (x>2 && x<800) mem_size=x*1024; } continue; } if (!stricmp(argv[i],"-BUF")) { if (i+1<argc) if (*argv[i+1]!='-') { x=atoi(argv[++i]); if (x>2 && x<800) buf_size=x*1024; } continue; } printf("Invalid Option: '%s'\n",argv[i]); } } int test_module() { register int c; int end_test=0; int result=0; register short i; char string[80]; register char *p; XSYMBOL *s; module_end=module_ptr=module_buffer; do { c=get_drct(); if (c<0) halt(2); if (module_end+128>module_top) halt(9); *module_end++=c; if (c==0xFB) { c=get_drct(); *module_end++=c; switch(c) { case -1 : halt(2); break; case 0xFB : break; case 0x01 : case 0x02 : i=get_drct(); *module_end++=i; while(i--) *module_end++=get_drct(); break; case 0x03 : case 0x05 : *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); break; case 0x12 : case 0x04 : *module_end++=get_drct(); *module_end++=get_drct(); break; case 0x06 : p=string; i=get_drct(); *module_end++=i; while (i--) { *p=get_drct(); *module_end++=*p++; } *p='\0'; *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); s=src_xsy(xsy_liste,string); if (s!=NULL) if (!(s->xsy_defd&1)) end_test=result=1; break; case 0x07 : *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); *module_end++=get_drct(); while (1) { c=get_drct(); *module_end++=c; if (c==0xFB || c==-1) break; *module_end++=get_drct(); *module_end++=get_drct(); } break; case 0x10 : *module_end++=get_drct(); *module_end++=get_drct(); i=get_drct(); *module_end++=i; while (i--) *module_end++=get_drct(); break; case 0x13 : end_test=1; break; default : halt(2); } } } while (!end_test); if (module_end>module_max) module_max=module_end; return(result); } void link_file(name,lib_mode) char *name; int lib_mode; { inp_hnd=Fopen(name,0); buf_ptr=buf_end=inp_buf+BLEN; strcpy(module_name,"*NO MODULE"); if (inp_hnd<0) { printf("Cannot open binary file: '%s'\n",name); exit(1); } nxsy(); while (sy.directive!=eofsy) { if (lib_mode) { if(!test_module()) { module_end=module_ptr=module_buffer; nxsy(); } else module(); } else module(); } Fclose(inp_hnd); } void write_prog() { int handle; int n,h; SECTION *sec; char *start,*endcode; if ((handle=Fcreate(program_name,0))<0) { printf("Cannot open %s for writing\n"); halt(10); } *((long*)&header[7])=debug_end-memstart; n=Fwrite(handle,28,header); if (n!=28) halt(10); if (spar_flag) { h=1; sec=sec_liste; start=membot; while (sec->sec_id>-2 && sec->sec_next!=NULL) sec=sec->sec_next; if (sec->sec_id==-2) { endcode=sec->sec_start; *((long*)&header[h])=endcode-start; if (endcode-start) { n=Fwrite(handle,endcode-start,start); if (n!=endcode-start) halt(10); } h=3; start=endcode; } while (sec->sec_id>-3 && sec->sec_next!=NULL) sec=sec->sec_next; if (sec->sec_id==-3) { endcode=sec->sec_start; { *((long*)&header[h])=endcode-start; if (endcode-start) { n=Fwrite(handle,endcode-start,start); if (n!=endcode-start) halt(10); } } h=5; start=endcode; } /* Rest in (h)-Section schreiben */ endcode=debug_start; *((long*)&header[h])=endcode-start; if (h<5) { if (endcode-start) { n=Fwrite(handle,endcode-start,start); if (n!=endcode-start) halt(10); } } } else { start=membot; endcode=debug_start; *((long*)&header[1])=debug_start-membot; if (endcode-start) { n=Fwrite(handle,endcode-start,start); if (n!=endcode-start) halt(10); } } /* Symboltabelle und Relocation Table schreiben */ *((long*)&header[7])=debug_end-debug_start; start=debug_start; endcode=code_ptr; if (endcode-start) { n=Fwrite(handle,endcode-start,start); if (n!=endcode-start) halt(10); } Fseek(0L,handle,0); n=Fwrite(handle,28,header); if (n!=28) halt(10); if (Fclose(handle)<0) halt(10); } void main(argc,argv) int argc; char *argv[]; { char line[80],*name; FILE *fp; int lib_mode; int err_code=0; printf(message); mem_size=100*1024; buf_size=32*1024; double_sym=undefd_sym=range_err=0; command_line(argc,argv); mod_liste=NULL; list_file=stdout; if (listing_flag) { list_file=fopen(listing_name,"w"); if (list_file==NULL) { printf("Cannot open list_file '%s' for writing\n"); exit(1); } if (list_file!=stdout) fprintf(list_file,message); } init_mem(); sec_liste=curr_sec=moved_sec=NULL; xsy_liste=NULL; xref_liste=NULL; altxref=NULL; if (control_flag) { fp=fopen(control_name,"r"); if (fp==NULL) { printf("Cannot open control_file : '%s'\n",control_name); exit(1); } while (!feof(fp)) { if ((name=fgets(line,80,fp))==NULL) *line='\0'; for (name=line; *name!='\n' && *name; name++); *name='\0'; if (!*line) continue; if (*line=='*') continue; name=NULL; lib_mode=0; if (!strnicmp(line,"INPUT",5)) name=line+5; else if (!strnicmp(line,"LIBRARY",7)) { name=line+7; lib_mode=1; } if (name==NULL) printf("Invalid control line : %s\n",line); else { name=stpblk(name); if (*name=='*') strmfe(name,file_name,"BIN"); else make_ext(name,name,"BIN"); link_file(name,lib_mode); } } fclose(fp); } else link_file(input_name,0); code_ptr=memstart; debug_start=code_ptr; if (debug_flag) debug_table(xsy_liste); debug_end=code_ptr; all_xrefs(sec_liste); statistic(); fprintf(list_file,"Program length = %8X\n",memstart-membot); fprintf(list_file,"Symbol table = %8X\n",debug_end-memstart); fprintf(list_file,"Relocation table = %8X\n",code_ptr-debug_end); fprintf(list_file,"--------------------\n"); fprintf(list_file, "Memory Usage = %7d%%\n",(code_ptr-membot)*100/mem_size); fprintf(list_file, "Buffer Usage = %7d%%\n",(module_max-module_buffer)*100/buf_size); fprintf(list_file,"--------------------\n"); list_xsy(xsy_liste,1); if (program_flag) write_prog(); if (symbol_flag) { fprintf(list_file,"\nSymbol Table:\n"); fprintf(list_file,"-------------\n"); list_xsy(xsy_liste,0); fprintf(list_file,"\n"); } if (undefd_sym) { if (list_file!=stdout) fprintf(list_file,"Undefined Symbols: %8d\n",undefd_sym); printf("Undefined Symbols: %8d\n",undefd_sym); err_code=1; } if (double_sym) { if (list_file!=stdout) fprintf(list_file,"Multiply defined : %8d\n",double_sym); printf("Multiply defined : %8d\n",double_sym); err_code=1; } if (range_err) { if (list_file!=stdout) fprintf(list_file,"Range errors : %8D\n",range_err); printf("Range errors : %8D\n",range_err); err_code=1; } printf("\nLink completed\n"); if (list_file!=stdout) fprintf(list_file,"\nLink completed\n"); if (listing_flag) fclose(list_file); exit(err_code); }