/* ---------------------------------------------------------------------- */ /* Copyright (C) 1991 by Natrlich! */ /* This file is copyrighted! */ /* Refer to the documentation for details. */ /* ---------------------------------------------------------------------- */ #define LIBRARIAN 1 #define __BIG_GENERATOR__ #include "defines.h" #include "nasm.h" #include #include #include "debug.h" #include "object.h" #include "lib.h" #if OS != TOS # include # if OS == UNIX # include # endif #endif #include OSBIND #include NMALLOC_H #include "code.h" #include "ldebug.h" #if ! VERSION extern char x1[], x2[], x3[], x4[], x5[], x6[]; char y1[] = " _GLOBALS ", y2[] = " _F_INDEX ", y3[] = " _OBJFILE "; #endif byte huge *__program, huge *__p, huge *ptohead; byte __c; word __pc, __x; lword __lx; static char trc_loss[] = "File is truncated"; static linksymbol huge *py; static obj_h l; static char huge *space; static char huge *p_space, huge *old_p_space; int version; #if ! VERSION int revision; #endif word gindex, findex; static lword bytes, sbytes, ibytes, rbytes, ebytes, ybytes, fbytes; static lword magic, gbytes, xbytes, cbytes, size, tbytes; static lword gsize; g_table globals[ MAXGLOBALS]; f_table files[ MAXFILES]; extern char *currfile; extern int laber; extern void fix_lversion(), fix_lsizes(); #if BIGENDIAN extern void flip_libstructs(); #endif #if VERSION # undef LIBMAX # define LIBMAX 0x4000L #endif #define SPARE 0x8000L void pro_init() { extern char outofmem[]; #if OS == TOS if( (size = (long) Malloc( -1L)) < SPARE) nferror("Space dangerously low *ouch* in here, aborting..."); p_space = space = nmalloc( size -= SPARE); /* leave 32K for symbols */ #else # if OS == UNIX || OS == AMIGA p_space = space = nmalloc( size = LIBMAX); /* ARGH! */ # else # if OS == MSDOS if( ! (p_space = space = nmalloc( size = LIBMAX))) nferror( outofmem); # else # error "missing code for your machinery" # endif # endif #endif if( laber) fprintf( ESTREAM, "%ld bytes space allocated for modules\n", size); } void pro_exit() { } #if VERSION #define thel10seek( x, y) #else void thel10seek( i, x) char *x; { unsigned long foo; static char chkbuf[11]; if( (foo = Fread( i, 10L, chkbuf)) < 10) ngferror( foo, trc_loss); if( strcmp( chkbuf, x)) nferror("Not a good NASM library file"); bcopy( chkbuf, p_space, 10L); p_space += 10; } #endif int lload( afile) char *afile; /* 3 'V's: Van Halen, VfL und Veltins! */ { static lib_h l; register long foo; int fd; ENTER("lload"); #if LOWERFILE downcase( afile); #endif IMESS( "Trying to open \"%s\" ", (long) afile, 4); if( (fd = (int) Fopen( afile, 0)) < 0) { if( fd == -35) nferror("Out of GEMDOS file handles (that's strange..) ?"); return( 0); } if( Fread( fd, sizeof( lib_h), &l) != sizeof( lib_h)) nferror("File is too short to be a library"); IMESS("Sizeof( lib_h) = %ld", (long) sizeof( lib_h), 4); magic = lbeek( &l.magic); version = dbeek( &l.version); #if ! VERSION revision = dbeek( &l.revision); #endif gbytes = gsize = lbeek( &l.gbytes); xbytes = lbeek( &l.xbytes); cbytes = lbeek( &l.cbytes); if( magic != LIBMAGIC) nferror("This is not a library"); #if BIGENDIAN if( version < DVERSION) #else if( version < LIB_READ_COMP) #endif nferror("Library was created with an obsolete version"); if( version > DVERSION) nferror("Librarian is too oldfashioned to understand object format"); #if ! VERSION if( revision != LIBREVISION) nferror("Library revision differs"); #endif if( version != DVERSION) fix_lsizes( version, &gsize); thel10seek( fd, y1); if( (foo = Fread( fd, gbytes, globals)) != gbytes) ngferror( foo, trc_loss); thel10seek( fd, y2); if( xbytes) if( (foo = Fread( fd, xbytes, &files[0])) != xbytes) ngferror( foo, trc_loss); thel10seek( fd, y3); if( cbytes) { if( (foo = Fread( fd, cbytes, space)) != cbytes) ngferror( foo, trc_loss); p_space += cbytes; } else p_space = space; Fclose( fd); if( version != DVERSION) fix_lversion( version, &gbytes, globals); gindex = (word) (gbytes / sizeof( g_table)); findex = (word) (xbytes / sizeof( f_table)); #if BIGENDIAN flip_libstructs( gindex, findex, globals, files); #endif if( laber) fprintf( ESTREAM, "Read in %s: %d modules with %d globals \ worth %ld bytes total\n", afile, findex, gindex, cbytes); LEAVE(); return(1); } void wrapup() { nfree( py); } void file_lib( currfile) char *currfile; { register char huge *src, huge *dst; register int i = FSIGNIFICANT; register f_table huge *p = &files[ findex++]; ENTER("file_lib"); src = get_filename( currfile); dst = p->name; while( (*dst++ = *src++) && i--); while( i--) *dst++ = 0; if( laber) fprintf( ESTREAM, "Put %.32s into library [%ld bytes]\n", currfile, tbytes); p->seek = old_p_space - space; #if OS == TOS p->time = Tgettime(); p->date = Tgetdate(); #else # if OS == MSDOS { struct time watch; struct date calendar; gettime( &watch); getdate( &calendar); p->time = ((unsigned) watch.ti_sec >> 1) | ((unsigned) watch.ti_min << 5) | ((unsigned) watch.ti_hour << 11); p->date = ((unsigned) calendar.da_year - 1980 << 9) | ((unsigned) calendar.da_mon - 1 << 5) | ((unsigned) calendar.da_day - 1); } # else { struct tm *watch; time_t the_time; if( (the_time = time( NULL)) == -1) nferror("Your system rudely refuses to give the current time"); watch = localtime( &the_time); p->time = ((unsigned) watch->tm_sec >> 1) | ((unsigned) watch->tm_min << 5) | ((unsigned) watch->tm_hour << 11); p->date = ((unsigned) watch->tm_year - 1900 << 9) | ((unsigned) watch->tm_mon << 5) | watch->tm_mday; } # endif #endif p->bytes = tbytes; LEAVE(); } int check_double( name) register char *name; { register char huge *s; register g_table huge *p = &globals[0]; register int i = gindex, j; static char buf[ SIGNIFICANT + 1]; while( i--) { s = p++->name; j = 0; while( *s++ == name[j++] && j < SIGNIFICANT); if( j >= SIGNIFICANT) { for( j = 0; j != SIGNIFICANT; buf[j++] = name[j]); buf[ SIGNIFICANT] = 0; nserror( "Symbol is already in the library", buf); return( 1); } } return(0); } void sym_lib() { register linksymbol huge *p = py; register char huge *dst, huge *src; register word i = (word) ybytes; int entered = 0; ENTER("sym_lib"); while( i--) { if( ! p->refs && ! check_double( p->name)) { if( gindex >= MAXGLOBALS) nferror("Sorry, global symbol table space exhausted"); dst = globals[ gindex].name; src = p->name; #if SIGNIFICANT == 8 *dst++ = *src++; /* SIGNIFICANT == 8 */ *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; *dst++ = *src++; /* eliminated one copy here */ *dst = *src; #else { register int j = SIGNIFICANT; while( j--) *dst++ = *src++; } #endif entered++; globals[ gindex++].index = findex; } p++; } if( ! entered) nferror("Module's unusuable 'coz there's no global label w/value"); LEAVE(); } #if VERSION # define S10EEKS 0 #else # define S10EEKS 6 * 10L #endif void oload( afile) char *afile; /* 3 'V's: Van Halen, VfL und Veltins! */ { register char *x; register long foo; int i; ENTER("oload"); #if LOWERFILE downcase( afile); #endif IMESS( "Trying to open \"%s\" ", (long) afile, 4); if( (i = (int) Fopen( afile, 0)) < 0) { MESS("Open failed"); strcpy( x = nmalloc( strlen( afile) + 5L), afile); complete( x, ".o65", 1); afile = x; if( (i = (int) Fopen( x, 0)) < 0) { if( i == -35) nferror("Out of GEMDOS file handles (that's strange..) ?"); nferror( "Object file does not exist"); } } if( Fread( i, sizeof( obj_h), &l) != sizeof( obj_h)) nferror("File is too short to be an object file"); IMESS("Sizeof( obj_h) = %ld", (long) sizeof( obj_h), 4); magic = lbeek( &l.magic); version = dbeek( &l.version); #if ! VERSION revision = dbeek( &l.revision); #endif bytes = (lword) dbeek( &l.codesize); sbytes = lbeek( &l.segsize); ibytes = lbeek( &l.immsize); rbytes = lbeek( &l.relsize); ebytes = lbeek( &l.expsize); ybytes = lbeek( &l.symsize); fbytes = lbeek( &l.fixsize); if( magic != OBJMAGIC) nferror("This is not an object file"); if( version < DVERSION) nferror("Object file was created with an obsolete version"); if( version > DVERSION) nferror("Librarian is to oldfashioned to understand this object format"); #if ! VERSION if( revision != ASMREVISION) nferror("Object file was made under old revision"); #endif if( ! ybytes) nwarning("Object file contains no global symbols"); tbytes = sbytes + ibytes + rbytes + ebytes + ybytes + fbytes + S10EEKS + bytes + sizeof( obj_h); if( ((old_p_space = p_space) - space) + tbytes > size) nferror("Can't fit all these files into memory"); bcopy( &l, p_space, (long) sizeof( obj_h)); p_space += sizeof( obj_h); if( (foo = Fread( i, bytes, p_space)) != bytes) ngferror( foo, trc_loss); p_space += bytes; thel10seek( i, x1); if( sbytes) { if( (foo = Fread( i, sbytes, p_space)) != sbytes) ngferror( foo, trc_loss); p_space += sbytes; } thel10seek( i, x2); if( ibytes) { if( (foo = Fread( i, ibytes, p_space)) != ibytes) ngferror( foo, trc_loss); p_space += ibytes; } thel10seek( i, x3); if( rbytes) { if( (foo = Fread( i, rbytes, p_space)) != rbytes) ngferror( foo, trc_loss); p_space += rbytes; } thel10seek( i, x4); if( ebytes) { if( (foo = Fread( i, ebytes, p_space)) != ebytes) ngferror( foo, trc_loss); p_space += ebytes; } thel10seek( i, x5); if( ybytes) { py = nmalloc( ybytes); if( (foo = Fread( i, ybytes, py)) != ybytes) ngferror( foo, trc_loss); bcopy( py, p_space, ybytes); p_space += ybytes; } thel10seek( i, x6); if( fbytes) { if( (foo = Fread( i, fbytes, p_space)) != fbytes) ngferror( foo, trc_loss); p_space += fbytes; } ybytes /= sizeof( linksymbol); #if BIGENDIAN fliplinks(); #endif LEAVE(); } #if BIGENDIAN void fliplinks() { register lword i; register word huge *q; register linksymbol huge *p; for( p = py, i = ybytes; i--; p++) { q = (word *) p; dswap( q); q++; /* val */ dswap( q); q++; /* no */ dswap( q); q++; /* type */ q++; /* dummy */ lswap( q); /* refs */ POINTER_CHECK( q); } } #endif void extract( afile) char *afile; { long size; int fp, i; for( i = findex; i--;) if( ! strcmp( files[i].name, afile)) { if( (fp = (int) Fkreate( currfile = afile, 0x664)) < 0) ngferror( fp, "Couldn't create output file"); if( Fwrite( fp, (size = files[i].bytes), space + files[ i].seek) != size) nferror("out of space"); Fclose( fp); return; } nserror("Module unknown", afile); } static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; void list( flag) { int i; unsigned j, k; printf("Modules in library:\n"); for( i = 0; i != findex; i++) { register f_table *p = &files[ i]; j = p->time; k = p->date; printf("%5.5ld bytes [%2.2d:%2.2d-%2.2d.%s.%d] : %-32s \n", p->bytes, j >> 11, (j >> 5) & 0x3F, k & 0x1F, months[ ((k >> 5) & 0xF) - 1], 1980 + (k >> 9), p->name); if( flag) { for( k = j = 0; j != gindex; j++) if( globals[ j].index == i) { if( ! k) putchar('\t'); printf("%-8s ", globals[j].name); if( ++k == 7) { k = 0; putchar( '\n'); } } if( k) putchar('\n'); } } } void delete( afile, flag) char *afile; { int i; #if LOWERFILE downcase( afile); #endif for( i = 0; i != findex; i++) { register f_table huge *p = &files[ i]; if( ! strcmp( p->name, afile)) { int j; lword k; long off; char huge *tmp; if( findex == 1) { p_space = space; findex = gindex = 0; } else { register f_table huge *q; k = p->bytes; off = p->seek; tmp = add_offset( space, off); if( i + 1 < findex) /* Collapse hole */ bcopy( tmp + k, tmp, cbytes - off - k); p_space -= k; for( q = p, j = 0; j != findex; q++, j++) /* Adjust seek adr */ if( q->seek > off) q->seek -= k; if( i < --findex) /* Remove from file table */ bcopy( (byte huge *) p + sizeof( f_table), p, (long) (findex - i) * sizeof( f_table)); for( k = j = 0; j != gindex; j++) /* Adjust index in globals */ { register g_table *p = &globals[ j]; if( p->index == i) { if( ! k++) off = j; } else if( p->index > i) p->index--; } if( k + off < gindex) bcopy( add_offset( globals, off + k), add_offset( globals, off), (long) (gindex - off) * sizeof( g_table)); gindex -= k; } if( laber) fprintf( ESTREAM, "Deleted module \"%s\"\n", p->name); return; } } if( ! flag) nserror("Object not in library", afile); } static char err[] = "Write to output file failed (Disk full??)"; void write_results( fd) { static lib_h libheader; register byte huge *p = (byte *) &libheader; lword gbytes, xbytes, cbytes; ENTER("write_results"); plbyte( p, LIBMAGIC); /* sort of stupid */ pdbyte( p, DVERSION); pdbyte( p, LIBREVISION); plbyte( p, gbytes = (byte huge *) &globals[ gindex] - (byte huge *) globals); plbyte( p, xbytes = (byte huge *) &files[ findex] - (byte huge *) files); plbyte( p, cbytes = p_space - space); #if BIGENDIAN flip_libstructs( gindex, findex, globals, files); /* do it here again */ #endif /* Compound this later on */ if( Fwrite( fd, sizeof( lib_h), &libheader) != sizeof( lib_h)) nferror( err); #if ! VERSION if( Fwrite( fd, 10L, y1) != 10L) nferror( err); #endif if( Fwrite( fd, gbytes, globals) != gbytes) nferror( err); #if ! VERSION if( Fwrite( fd, 10L, y2) != 10L) nferror( err); #endif if( Fwrite( fd, xbytes, &files[0]) != xbytes) nferror( err); #if ! VERSION if( Fwrite( fd, 10L, y3) != 10L) nferror( err); #endif if( Fwrite( fd, cbytes, space) != cbytes) nferror( err); Fclose( fd); LEAVE(); }