/* File: include.c * * Contains: include, glink, linkx, glinkx, gl, look, swap, * cgenv, strip, search * * These routines open up, for reading, an include file, and * link or glink request. * If the request is an 'include', then it came from the command * file. If a link/glink request, it came from the relocatable * object file. */ #include "link.h" #define GBSIZE 19 /* number of bytes in old .gbl file */ extern unsigned char cname2[]; extern unsigned char timeb[]; extern unsigned char passno; extern unsigned char log; extern unsigned char *who; extern unsigned int inclf; extern unsigned int psectcount; extern int slenth; extern FILE *infile; extern FILE *logfile; static unsigned char tempname[80]; static unsigned char filename[80]; static FILE *fp; static unsigned char eof; FILE *efile; unsigned char *look(); FILE *tryopen(); SYM *locate(); /* * This routine reads in a line of relocatable object from the * input file and returns the next byte. */ unsigned char getbyte() { register int byte; for(;;) { if((byte = fgetc(infile)) < 0) { printl("Unexpected EOF\n"); xdone(1); } return((unsigned char) byte); } } include() { register FILE *sp; register unsigned int inclfx; unsigned char *save; unsigned char incfile[80]; strcpy(incfile, cname2); strip(incfile); addext(incfile, ".rel"); if(tryopen(incfile) == NULL) { printl("Can't load: %s\n", filename); xdone(1); } ++psectcount; gettime(); printl("LOAD:\t%s", incfile); if(log) printl(" at: %s", timeb); printl("\n"); save = who; who = incfile; sp = infile; infile = fp; inclfx = inclf; inclf = 1; fgetc(infile); /* read in the 'more' header and */ fgetc(infile); /* throw it away */ xlink(); fclose(infile); infile = sp; who = save; inclf = inclfx; } /* this routine is used when a file is to be linked in, the request coming from an object file. */ linkx() { register unsigned char *save; register unsigned int inclfx; register FILE *sp, *fpx; unsigned char linkfile[80]; readsym(linkfile); addext(linkfile, ".rel"); if((fpx = tryopen(linkfile)) == NULL) { printl("Can't link: %s\n", linkfile); return; } ++psectcount; gettime(); printl("LINK:\t%s", linkfile); if(log) printl(" at: %s", timeb); printl("\n"); save = who; who = linkfile; sp = infile; infile = fpx; inclfx = inclf; inclf = 1; fgetc(infile); /* read in the 'more' header and */ fgetc(infile); /* throw it away */ xlink(); fclose(infile); infile = sp; who = save; inclf = inclfx; } /* read in a global file. This request is from the command file */ glink() { unsigned char incfile[80]; strcpy(incfile, cname2); gl(incfile); } /* read in a global file. called from the object request */ glinkx() { unsigned char gblfile[80]; readsym(gblfile); gl(gblfile); } /* This is the routine that reads in an EXTernal file and adds * the labels and values to the symbol table. */ gl(buffer) unsigned char *buffer; { extern unsigned char get_byte(); register GBL *gp; register SYM *sp; register unsigned char *tp; unsigned char which, flag; register unsigned int i, word; unsigned char xbuff[80]; if(passno != 1) return; strip(buffer); addext(buffer, ".gbl"); eof = 0; if((efile = tryopen(buffer)) == NULL) { tp = look(buffer); sprintf(xbuff, "/usr/include/%s", tp); if((efile = tryopen(xbuff)) == NULL) { printl("Open failure on GBL file: %s and %s\n", buffer, xbuff); return; } strcpy(buffer, xbuff); } gettime(); printl("GBL:\t%s", buffer); if(log) printl(" at: %s", timeb); printl("\n"); which = fgetc(efile); ungetc(which, efile); /* check old style global file read */ if(which == ':' || which == '0') { printl("reading old style global file\n"); flag = 0; while(!eof) { tp = xbuff; for(i = 0; i < GBSIZE; i++) { *tp = get_byte(efile); ++tp; } if(flag && xbuff[6]) { word = (xbuff[5] << 8) + xbuff[4]; tp = &xbuff[6]; if(sp = locate(tp)) { if(!(sp->flag & LNKENT)) { sp->flag |= (LNKENT | LNKGBL); sp->value = word; } } else insert(tp, word, LNKENT|LNKGBL); } flag = 1; } } else { gp = (GBL *) xbuff; fread(gp, GSIZE, 1, efile); if((gp->g_flag1 != O6H) || (gp->g_flag2 != O6GBL)) { fclose(efile); printl("%s is not a GBL file\n", buffer); return; } while(fread(gp, GSIZE, 1, efile) != 0) { if(sp = locate(gp->g_name)) { if(!(sp->flag & LNKENT)) { sp->flag |= (LNKENT | LNKGBL); sp->value = gp->g_value; } } else insert(gp->g_name, gp->g_value, LNKENT|LNKGBL); } } fclose(efile); } static unsigned char get_byte() { unsigned char byte; int x; for(;;) { if((x = fgetc(efile)) <= 0) { eof = 1; return(0); } if(x == '\n' || x == ':') continue; x -= x > '9' ? '7' : '0'; byte = x << 4; x = fgetc(efile); x -= x > '9' ? '7' : '0'; return(byte |= x); } } /* this routine will look at a filename and return a pointer to the name itself bypassing any path. */ unsigned char *look(pointer) register unsigned char *pointer; { register unsigned char *pnt1; pnt1 = pointer; while(*pointer) { if(*pointer == '/') pnt1 = ++pointer; else ++pointer; } return(pnt1); } /* This routine gets a pointer to the filename itself bypassing any path, then will reverse the case (upper/lower) of the filename. */ swap(pointer) register unsigned char *pointer; { pointer = look(pointer); while(*pointer) { if(((*pointer >= 'A') && (*pointer <= 'Z')) || ((*pointer >= 'a') && (*pointer <= 'z'))) *pointer ^= ' '; ++pointer; } } /* This routine will get an environment variable for path name substitution. */ unsigned char *cgenv(pnt) register unsigned char *pnt; { register unsigned char *ev; unsigned char *getenv(); if((ev = getenv(pnt)) == NULL) { swap(pnt); if((ev = getenv(pnt)) == NULL) return(pnt); } strcpy(pnt, ev); if(pnt[strlen(pnt)-1] != '/') strcat(pnt, "/"); return(&pnt[strlen(pnt)]); } /* This routine is used to insure that a file name is properly terminated. */ strip(ptr) register unsigned char *ptr; { while(*ptr) { if((*ptr == '\'') || (*ptr <= ' ')) { *ptr = 0; break; } ++ptr; } } /* This routine will attempt to open a file. If successful, it will return the file pointer. If not, it will reverse the case (upper/lower) of the name (only, not path) and attempt the open again. If good, it will return the pointer, else return NULL. If an environment variable is found, it will be expanded if possible. */ FILE *tryopen(ptr) register unsigned char *ptr; { register unsigned char *bp, *cp; strcpy(tempname, ptr); strip(tempname); bp = tempname; cp = filename; while(*bp) { if(*bp == ':') cp = cgenv(filename); else { *cp++ = *bp; *cp = 0; } ++bp; } *cp = 0; if((fp = fopen(filename, "r")) == NULL) { swap(filename); if((fp = fopen(filename, "r")) == NULL) return(NULL); } return(fp); } /* search for an extension */ unsigned char *search(pnt) register unsigned char *pnt; { pnt = look(pnt); while(*pnt) { if(strncmp(pnt, "../", 3) == 0) pnt += 3; else if(*pnt == '.') return(pnt); ++pnt; } return(NULL); } readsym(buffer) register unsigned char *buffer; { register unsigned int i; unsigned char x; for(i = 0; i < slenth; i++) { x = getbyte(); buffer[i] = (x == ' ') ? 0 : x; } buffer[i] = 0; } read1sym(buffer) register unsigned char *buffer; { register unsigned int i; unsigned char x; for(i = 0; i < 20; i++) { x = getbyte(); buffer[i] = (x == ' ') ? 0 : x; } buffer[i] = 0; } addext(buffer, extension) register unsigned char *buffer, *extension; { register unsigned char *tp; if(search(buffer) == NULL) { tp = look(buffer); if(*tp >= 'A' && *tp <= 'Z') strcat(buffer, swap(extension)); else strcat(buffer, extension); } } force_extension(from, to, extension) register unsigned char *from, *to, *extension; { register unsigned char *sp; strcpy(to, from); if(sp = search(to)) *sp = 0; addext(to, extension); }