/* ---------------------------------------------------------------------- */ /* Copyright (C) 1992 by Natrlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ #define LINKER 1 #include "defines.h" #include #include #include #include OSBIND #include "nasm.h" #include "debug.h" #include NMALLOC_H #include "code.h" #if STATISTICS # include #endif #define STDORIGIN 0x2000 #define MAXFILES 256 /* max files to link together */ #define MAXLIBS 16 char *currfile; static char *infile[MAXFILES], *libraries[ MAXLIBS], linkfile[ 256], outfile[ 256], #if OS == TOS _usage[] = "Usage:\nnlink65 [-{tiwv}][-m [xxxx]][-s *][-b batch][-d ldir][-l lib]\ [-o com] \n", #else _usage[] = "Usage:\nnlink65 [-{wiv}][-m [xxxx]][-s *][-b batch][-d ldir][-l lib]\ [-o com] \n", #if PORTED portnoy[] = { # if INCOMPATIBLE 'W','a','r','n','i','n','g',':',' ','O','b','j','e','c','t',' ', 'f','i','l','e',' ', 'i','n','c','o','m','p','a','t','i','b','i','l','t','y','.',' ', # endif 'P','o','r','t','e','d',' ','b','y',' ',PORTER,'\n', 0 }, # endif #endif notice[] = { 'N','l','i','n','k','6','5',' ','v',VERSION+'0','.', LINKREVISION/10+'0',LINKREVISION%10+'0',' ', 'b','y',' ',AUTHOR,' ',' ','C','o','p','y','r','i','g','h','t',' ', '(','c',')',' ','1','9','9','2',' ',ORGANIZATION,'\r','\n',0 }; extern seg *sp; seg *l_seg; char header[128]; int relocatable, moveable, dumpvalues, verbose, runad, pageflag = 1, #if OS == TOS tossable, #endif what_the_fuck, /* cited from "Everybody wants some" */ bootable, fdout, files, #if STATISTICS tok_remain, #endif libs, maxerrors = 20; word relative = 743, mv_offset, origin = STDORIGIN; extern int freshflag, errors; void main( argc, argv) int argc; char **argv; { #if STATISTICS clock_t t_start, t_finish, t_result, t_tmp; #endif char *x; int i = 0, foo; ENTER("main"); #if STATISTICS t_start = clock(); #endif if( x = getenv( "LIB65")) { strcpy( header, x); fixheader(); } #if OS == TOS else tossable = 1; #endif #if DEBUG if( argc > 1) printf("Argc=%d argv[1]=\"%s\"\n", argc, argv[1]); #endif while( ++i < argc) if( *argv[i] == '-') switch( Xtolower( argv[i][1])) { case 'b' : { register char c; FILE *fp, *fopen(); static char x[256]; if( ++i >= argc) goto usage; strcpy( linkfile, argv[i]); complete( linkfile, ".lnk", 0); if( ! (fp = fopen( linkfile, "r"))) nferror("Opening the linkfile failed"); do switch( c = getc( fp)) { case '#' : while( (c = getc( fp)) != '\n' && c != EOF); break; default : { register int i = 0; do x[i++] = c; while( (c = getc( fp)) != ' ' && c != '\t' && c != '\r' && c != '\n' && c != EOF && i < 255); x[i++] = 0; infile[ files++] = strcpy( (char *) nmalloc( (long) i), x); } case ' ' : case '\t' : case '\r' : case '\n' : case EOF : ; } while( c != EOF); fclose( fp); } break; case 'd' : if( ++i == argc) goto usage; strcpy( header, argv[i]); fixheader(); break; case 'i' : runad = ! runad; break; case 'l' : if( ++i >= argc) goto usage; libraries[ libs++] = argv[i]; break; case 'm' : switch( argv[i][2]) { case 'm' : relocatable = -9; moveable = 1; case '3' : relocatable += 2; case '2' : if( ++i == argc || ! sscanf( argv[i],"%X", &foo)) default : goto usage; relative = foo; relocatable += 2; case '1' : relocatable++; case '0' : case 0 : if( pageflag) pageflag = ++relocatable & 2; /* **-Port #7-** */ } break; case 'o' : if( ++i == argc) default : goto usage; strcpy( outfile, argv[i]); break; case 's' : if( ++i >= argc || ! sscanf( argv[i], "%X", &foo)) goto usage; if( (origin = foo) < 0x100) nwarning("Zeropage destination"); else if( origin < 0x200) nwarning("Stack destination"); if( pageflag) pageflag = ! (origin & 0xFF); break; #if OS == TOS case 't' : tossable = ! tossable; break; #endif #ifdef __DATE__ case ':' : fputs( __DATE__, stderr); # ifdef __TIME__ fprintf( stderr, " %s", __TIME__); # endif putc( '\n', stderr); break; #endif case 'v' : if( Xtolower( argv[ i][2]) == 'f') { dumpvalues = ! dumpvalues; if( Xtolower( argv[ i][3]) != 'l') break; } verbose = ! verbose; break; case 'w' : what_the_fuck = ! what_the_fuck; break; case 'x' : { char *p = &argv[i][2]; bootable = ! bootable; if( *p) { if( *p == ':') bootable++; if( ! sscanf( p, "%X", &foo)) goto usage; define( "_BOOT_INIT", (word) foo); } } } else infile[files++] = argv[i]; if( ! infile[0]) goto usage; #if OS == MSDOS _fmode = O_BINARY; #endif Cconws( notice); #if ! VERSION Cconws("unfinished - unstable - unsupported -- untested. Don't use it!\r\n"); version0(); #endif #if PORTED Cconws( portnoy); #endif if( relocatable && pageflag) origin = (origin & 0xFF00) - 3; if( moveable) mv_offset = relative - origin; pro_init(); #if VERSION sexp_alloc(); #endif for( i = 0; i != files; i++) if( (x = strrchr( currfile = infile[ i], '.')) && x[ 1] == 'l') lload( currfile); else aload( currfile, 0); if( lerr_undefs( 1)) for( i = 0; i != libs; i++) lload( currfile = libraries[ i]); if( lerr_undefs( 1)) lload( currfile = "std.l65"); currfile = 0; /* YOU CAN'T DO ANYTHING BELOW THIS POINT IN TERMS OF LIST */ /* MANAGEMENT LOADING OF FILES ET.C. */ lerr_undefs( 0); #if ! VERSION if( ! errors) lerr_imms(); #endif if( relocatable) { extern word __pc, r_end, head_off; r_end = __pc; dpoke( __program + head_off - 2, r_end); /* Fix JSR to RELOC.O65 */ def_label( "|MEMLO", relative); def_label( "|R_END", __pc); l_seg = sp; if( ! moveable) { aload( currfile = (pageflag ? "preloc.o65" : "breloc.o65"), 1); dump_reloc(); dump_imm( pageflag); } else aload( currfile = "mover.o65", 1); #if ! VERSION if( ! errors) lerr_undefs( 0); #endif } if( dumpvalues) show_values(); pro_exit(); if( ! outfile[0]) { strcpy( outfile, infile[0]); complete( outfile, bootable ? ".boo" : ".com", 1); } #if ! DEBUG if( ! errors || what_the_fuck) { #endif if( (fdout = (int) Fkreate( outfile, 0x775)) < 0) nferror("Can't create output file"); write_results( fdout); #if ! DEBUG } #endif MESS("OK JUST ABOUT DONE"); #if STATISTICS t_finish = clock(); if( t_start > t_finish) t_tmp = t_start - t_finish; else t_tmp = t_finish - t_start; t_result = (t_finish - t_start) / (word) CLK_TCK; finalstats(1); printf("Link took %ld.%lds\n", t_result, (t_tmp - (t_result * (word) CLK_TCK)) >> 1 ); stats(); #endif LEAVE(); nexit( errors ? 1 : 0); usage: fputs( _usage, ESTREAM); fputs( "\ \t-v : verbose\n\ \t-i : append RUNAD for DOS 2.X\n\ \t-x[binit] : create boot sectors (restrictions may apply)\n\ \t-w : write output file anyway (W.T.F.)\n\ \t-m[0] : mover to (LOMEM) [Default]\n\ \t-m1 : mover to (LOMEM) page aligned\n\ \t-m2 : mover to (xxxx)\n\ \t-m3 : mover to (xxxx) page aligned\n\ \t-mm : mover to xxxx\n\ \t-s : origin to load/run binary at\n\ \t-d : default directory\n\ \t-o : output file\n\ \t-b : take input files from batchfile\n\ \t-l : libraries to use\n", ESTREAM); #if OS == TOS fputs( "\ \t-t : wait for keypress before exit\n", ESTREAM); #endif LEAVE(); nexit( 1); } void fixheader() { static char foo[] = { DIRSLASH, 0 }; ENTER("fixheader"); if( header[ strlen( header)] != DIRSLASH) strcat( header, foo); #if DEBUG printf("Current include-path : \"%s\" \n", header); #endif LEAVE(); }