/* omflibcp.c (emx+gcc) -- Copyright (c) 1993-1996 by Eberhard Mattes */ /* Copy a module from one OMFLIB to another OMFLIB. */ #include #include #include #include "omflib0.h" #include static struct omflib *pubdef_dst_lib; static word pubdef_page; static int add_pubdef (const char *name, char *error); int omflib_copy_module (struct omflib *dst_lib, FILE *dst_file, struct omflib *src_lib, FILE *src_file, const char *mod_name, char *error) { struct omf_rec rec; word page; long long_page, pos; char theadr_name[256]; char libmod_name[256]; char caller_name[256]; byte buf[1024], buf2[256+6]; enum omf_state state; enum {RT_THEADR, RT_OTHER} cur_rt, prev_rt; int copy; theadr_name[0] = 0; libmod_name[0] = 0; if (mod_name == NULL) caller_name[0] = 0; else omflib_module_name (caller_name, mod_name); if (dst_lib != NULL) { long_page = ftell (dst_file) / dst_lib->page_size; if (long_page > 65535) { strcpy (error, "Library too big -- increase page size"); return -1; } page = (word)long_page; } else page = 0; state = OS_EMPTY; prev_rt = RT_OTHER; do { if (fread (&rec, sizeof (rec), 1, src_file) != 1) goto failure_src; if (rec.rec_len > sizeof (buf)) { strcpy (error, "Record too long"); return -1; } if (fread (buf, rec.rec_len, 1, src_file) != 1) goto failure_src; copy = TRUE; cur_rt = RT_OTHER; switch (rec.rec_type) { case THEADR: if (rec.rec_len == 0 || buf[0] + 1 > rec.rec_len) { strcpy (error, "Truncated THEADR record"); return -1; } buf[1+buf[0]] = 0; omflib_module_name (theadr_name, buf + 1); state = OS_EMPTY; cur_rt = RT_THEADR; break; case PUBDEF: case PUBDEF|REC32: if (dst_lib != NULL) { pubdef_dst_lib = dst_lib; pubdef_page = page; if (omflib_pubdef (&rec, buf, page, add_pubdef, error) != 0) return -1; } state = OS_OTHER; break; case ALIAS: if (dst_lib != NULL) { pubdef_dst_lib = dst_lib; pubdef_page = page; if (omflib_alias (&rec, buf, page, add_pubdef, error) != 0) return -1; } state = (state == OS_EMPTY ? OS_SIMPLE : OS_OTHER); break; case COMENT: if (rec.rec_len >= 3 && buf[1] == IMPDEF_CLASS && buf[2] == IMPDEF_SUBTYPE) { if (dst_lib != NULL) { pubdef_dst_lib = dst_lib; pubdef_page = page; if (omflib_impdef (&rec, buf, page, add_pubdef, error) != 0) return -1; } state = (state == OS_EMPTY ? OS_SIMPLE : OS_OTHER); } else if (rec.rec_len >= 2 && buf[1] == LIBMOD_CLASS) { if (dst_lib == NULL || mod_name != NULL) copy = FALSE; if (rec.rec_len < 3 || buf[2] + 3 > rec.rec_len) { strcpy (error, "Truncated LIBMOD record"); return -1; } buf[3+buf[2]] = 0; omflib_module_name (libmod_name, buf + 3); state = OS_OTHER; } else state = OS_OTHER; break; case MODEND: case MODEND|REC32: /* Don't change STATE. */ break; default: state = OS_OTHER; } if (prev_rt == RT_THEADR && dst_lib != NULL && mod_name != NULL) { if (state == OS_SIMPLE) cur_rt = RT_THEADR; /* Check again after next record */ else if (strcmp (caller_name, theadr_name) != 0) { buf2[0] = 0; buf2[1] = LIBMOD_CLASS; buf2[2] = strlen (caller_name); memcpy (buf2 + 3, caller_name, buf2[2]); if (omflib_write_record (dst_lib, COMENT, buf2[2] + 3, buf2, TRUE, error) != 0) return -1; } } if (copy && dst_file != NULL) { if (fwrite (&rec, sizeof (rec), 1, dst_file) != 1 || fwrite (buf, rec.rec_len, 1, dst_file) != 1) return omflib_set_error (error); } prev_rt = cur_rt; } while (rec.rec_type != MODEND && rec.rec_type != (MODEND|REC32)); if (src_lib != NULL) { pos = ftell (src_file); if (pos % src_lib->page_size != 0) fseek (src_file, src_lib->page_size - pos % src_lib->page_size, SEEK_CUR); } if (dst_lib != NULL) { /* Don't use PUBDEF for the module name for modules that contain only an alias or an import definition. */ if (state != OS_SIMPLE) { if (caller_name[0] != 0) strcpy (buf2, caller_name); else if (libmod_name[0] != 0) strcpy (buf2, libmod_name); else strcpy (buf2, theadr_name); strcat (buf2, "!"); if (omflib_add_pub (dst_lib, buf2, page, error) != 0) return -1; } if (dst_file != NULL && omflib_pad (dst_file, dst_lib->page_size, FALSE, error) != 0) return -1; } return 0; failure_src: if (ferror (src_file)) return omflib_set_error (error); strcpy (error, "Unexpected end of file"); return -1; } static int add_pubdef (const char *name, char *error) { return omflib_add_pub (pubdef_dst_lib, name, pubdef_page, error); }