/* * b u i l d 3 . c * * Link magic */ #include #include "build.h" /* * The following parameters define the number of files that are * written to each line of the link/libr command string. They * were set (by painful inspection) so that command lines would * not exceed 80 bytes in length. Note that very long command files * would be fatal on RSX-11M and RSTS/E where fixed-length command * buffers would overflow. */ #define RT_NOBJ 4 /* RT11 native and RSTS/E RT */ #define RX_NOBJ 3 /* RSX-11M all flavors */ #define VX_NOBJ 6 /* Vax native */ /* * These tables define the library list to be appended to compilations */ static char *vxlib[] = { "LIBS", "UTLIB", "VXLIB", NULL }; static char *rxlib[] = { "DTOA", "LIBS", "UTLIB", "RXLIB", NULL }; static char *rtlib[] = { "DTOA", "LIBS", "UTLIB", "SUPORT", "RTLIB", NULL }; static char *nolib[] = { NULL }; dolink() /* * Build link strings. Very magical. * * The basic problem is that, if there are more than (say) four files, * the link command must be broken into several lines. This isn't * particularily easy. */ { register int manyfiles; /* Number of files */ register char *tp; /* Text (odl) pointer */ register char *filestring; /* File name string */ int deleteodl; /* Must delete odl file if set */ deleteodl = FALSE; filestring = syvalue((isdefault("OBJS") ? "FILES" : "OBJS")); if (filestring == NULL) { fprintf(stderr, "warning: how can I link nothing\n"); return; } switch (op_type) { case VBOTH: objs(filestring, "VXOBJS", vxlib, VX_NOBJ, 3, ",-\n "); case VRSX: case RSTSRSX: case RSXNATIVE: if ((tp = syvalue("ODL")) != NULL && *tp != EOS) { /* * We have to create an odl file */ expout("$(COPYODL)"); sysave("RXOBJS", "$(RXODL)"); manyfiles = FALSE; deleteodl = TRUE; } else { manyfiles = objs(filestring, "RXOBJS", rxlib, RX_NOBJ, 0, "\n"); } if (op_type == RSXNATIVE && isdefault("TKBOPTIONS")) { /* * Force a TASK=...FOO */ sprintf(work, "%sXXX", syvalue("PROGRAM")); work[3] = EOS; sysave("TASKNAME", work); sysave("TKBOPTIONS", "TASK = ...$(TASKNAME)\n"); fprintf(stderr, "Note: task name of %s set to ...%s\n", syvalue("PROGRAM"), work); } if (!isdefault("TKBOPTIONS")) { sysave("RXARGS", (isdefault("ODL")) ? "\n/\n$(TKBOPTIONS)//" : "\n$(TKBOPTIONS)//", 0); manyfiles = TRUE; } if (manyfiles) { sysave("LINK1", "\n", 0); } break; case VNATIVE: objs(filestring, "VXOBJS", vxlib, VX_NOBJ, 3, ",-\n "); break; case RSTSRT: case RT11NATIVE: if (!isdefault("OVR")) { sysave("RTOBJS", "$(OVR)"); manyfiles = TRUE; } else { manyfiles = objs(filestring, "RTOBJS", rtlib, RT_NOBJ, 0, "\n"); } if (manyfiles) { sysave("LINK1", "/B:$(STACK)//\n", 0); sysave("LINK2", "//\n$(EXIT)", 0); } else { sysave("LINK2", "/B:$(STACK)\n$(EXIT)", 0); } break; default: fatal("dolink"); } expout("$(LINK)$(ALLOWEXECUTE)"); if (deleteodl) expout("$(DELETEODL)"); } dolibr(filestring) char *filestring; /* * Build link strings. Very magical. * * The basic problem is that, if there are more than six files, * the link command must be broken into several lines. This isn't * particularily easy. */ { register SYMBOL *sy; register char *np; register char *filename; /* * Hack the library name. If the user supplied a filetype, * we're all done. Else, append .ODL or .OBJ as needed. */ setstrip(lib_name, EOS, "?", NULL); sy = sylookup("?", FALSE); filename = sy->sy_value; np = &filename[strlen(filename)]; while (np > filename && *--np != '.' && *np != ')' && *np != ']' && *np != ':'); if (*np != '.') { /* * User didn't supply a .ext, so we shall do so. */ switch (op_type) { case VBOTH: case VRSX: case VNATIVE: case RSXNATIVE: sy->sy_value = csavest(filename, ".OLB"); break; case RSTSRT: case RT11NATIVE: sy->sy_value = csavest(filename, ".OBJ"); break; } } if (filestring == NULL) { fprintf(stderr, "warning: how can I build nothing\n"); return; } switch (op_type) { case VBOTH: objs(filestring, "VXOBJS", nolib, VX_NOBJ, 3, ",-\n "); case VRSX: case RSTSRSX: case RSXNATIVE: objs(filestring, "RXOBJS", nolib, RX_NOBJ, 0, "\n$(LBR.1) $?="); break; case VNATIVE: objs(filestring, "VXOBJS", nolib, VX_NOBJ, 3, ",-\n "); break; case RSTSRT: case RT11NATIVE: if (objs(filestring, "RTOBJS", nolib, RT_NOBJ, 0, "\n")) { sysave("LINK1", "//\n", 0); sysave("LINK2", "//\n$(EXIT)", 0); } else { sysave("LINK2", "\n$(EXIT)", 0); } break; default: fatal("dolibr"); } expout("$(LIBRARY)$(ALLOWREAD)"); } static int obj_nfiles; static int obj_first; static int objs(filestring, name, lib, nperline, initial_nfiles, separator) char *filestring; /* Files to expand */ char *name; /* Symbol to define */ register char *lib[]; /* libraries to expand */ int nperline; /* Number of symbols per line */ int initial_nfiles; /* Initial value for obj_nfiles */ char *separator; /* String to separate lines */ /* * Build a string containing the list of object files, including the * default library. obj() returns true if more than nperline files * were saved. * * The string is savest'ed under "name". If more than nperline * files are requested, lines will be separated using "separator". * * Uses work. * * Note: the purpose of nperline (and initial_nfiles) is to prevent * command lines from growing beyond column 80 (which is fatal on * RSX-11M). The correct way to do this would be to expand the command * before inserting seperators. The values chosen here may not be * small enough for 9-byte long RSX file names. */ { register char *wp; register char *libtext; char *objexpand(); obj_nfiles = initial_nfiles; obj_first = TRUE; /* Supress first ',' */ wp = objexpand(filestring, work, nperline, separator, TRUE); while (*lib != NULL) { /* Do all libraries for opsys */ if ((libtext = syvalue(*lib)) != NULL) { wp = objexpand(libtext, wp, nperline, separator, FALSE); } lib++; } sysave(name, work, 0); return(obj_nfiles > nperline); } static char * objexpand(string, buffer, nperline, separator, forcefiletype) char *string; /* Where it comes from */ char *buffer; /* Where it goes to */ int nperline; /* Files per line */ char *separator; /* Between lines string */ int forcefiletype; /* TRUE to force .obj */ /* * Copy the string to the work buffer, counting files. */ { register char *s; /* Input string pointer */ register char *b; /* Output string pointer */ register int c; /* Current character */ char *nptr; /* Nperline pointer */ int inacct; /* True if copying [...] */ int skipit; /* True if not copying ".ext" */ s = string; b = buffer; while ((c = *(s = skipwhite(s))) != EOS) { s++; if (b >= &work[WORKSIZE]) fatal("work buffer overflow in objs()"); while (iswhite(c) || c == ',') c = *s++; if (c == EOS) break; /* * Separate the new one from the previous ones. */ if (obj_first) { obj_first = FALSE; /* No comma first time */ } else { if ((obj_nfiles % nperline) != 0) { *b++ = ','; /* Normal */ } else { /* * Big separation here */ for (nptr = separator; *nptr != EOS;) *b++ = *nptr++; } } /* * C has the first byte of the new object file, * copy the file name to the buffer. */ inacct = FALSE; /* Not in [...] */ skipit = 0; /* Not at ".ext" */ while (!iswhite(c) && c != EOS && (c != ',' || inacct > 0)) { if (c == '(' || c == '[') inacct++; /* TRUE should suffice */ else if (c == ']' || c == ')') inacct--; /* FALSE should suffice */ else if (!inacct && forcefiletype && c == '.') skipit = TRUE; /* Skip over ".ext;foo" */ if (!skipit) *b++ = toupper(c); c = *s++; } if (inacct != 0) { *b = EOS; fprintf(stderr, "Bad file name in buffer: \"%s\"\n", buffer); } if (forcefiletype) { *b++ = '.'; /* Force the .obj */ *b++ = 'O'; /* Filetype to fool the */ *b++ = 'B'; /* dreaded vms logical */ *b++ = 'J'; /* name expander */ } obj_nfiles++; /* Here is a file */ if (c == EOS) break; } *b = EOS; return (b); }