/* * b u i l d 3 . c * * Link and Unix 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 4 /* Vax native */ #define UX_NOBJ 6 /* Unix native */ /* * These tables define the library list to be appended to compilations */ static char *vxlib[] = { "LIBS", "UTLIB", "DECUS_LIB", "VXLIB", NULL }; static char *rxlib[] = { "DTOA", "ATOF", "LIBS", "UTLIB", "RXLIB", NULL }; static char *rtlib[] = { "DTOA", "ATOF", "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 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", NULL); } expout("$(LINK)$(ALLOWEXECUTE)"); if (deleteodl) expout("$(DELETEODL)"); } dounix(files) register char *files; /* * Build string for Unix make */ { extern char *fixfiletype(); register char *filestring; if ((filestring = syvalue(files)) == NULL) { fprintf(stderr, "warning: how can I make nothing\n"); return; } /* * Get the object file names, then force newline where needed. */ files = savest(fixfiletype(filestring, ".o")); objs(files, "UXFILES", nolib, UX_NOBJ, 0, " ", "\\\n\t"); free(files); /* * Do the make, then name the include files */ expout("$(UXMAKE)"); doeach("INCLUDE", "UXINCLUDE", NULL); } char * fixfiletype(filestring, filetype) char *filestring; /* separated file list */ char *filetype; /* ".c" or whatever */ /* * This routine forces the approved filetype. Result in work[]. */ { register char *in; register char *outp; register char c; char *tp; in = filestring; outp = work; while ((c = *(in = skipwhite(in))) != EOS) { if (outp >= &work[WORKSIZE]) { fatal("Work buffer overflow in fixfiletype", filestring); } /* * skip over whitespace before filename * c == *in -> first non-white (may be a comma). */ while (iswhite(c) || c == ',') c = *++in; if (c == EOS) break; *outp++ = ' '; /* * copy file name. */ while (!iswhite(c) && c != EOS && c != '.') { *outp++ = c; c = *++in; } /* * c == *in -> first byte past filename */ if (c == '.') { /* * skip over existing filetype */ do { c = *++in; } while (!iswhite(c) && c != EOS); } for (tp = filetype; (*outp = *tp++) != EOS;) outp++; if (c == EOS) break; } *outp = EOS; return (work); } 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 && strchr(".)]:", *--np) == NULL); if (*np != '.') { /* * User didn't supply a .ext, so we shall do so. */ switch (op_type) { case VRSX: case VNATIVE: case RSXNATIVE: case RSTSRSX: sy->sy_value = csavest(filename, ".OLB"); break; case RSTSRT: case RT11NATIVE: sy->sy_value = csavest(filename, ".OBJ"); break; default: fatal("dolibr -- bad optype @ def. ext.", NULL); } } if (filestring == NULL) { fprintf(stderr, "warning: how can I build nothing\n"); return; } switch (op_type) { 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$(VXLIBR.1) "); 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", NULL); } expout("$(LIBRARY)$(ALLOWREAD)"); } static int obj_nfiles; static int obj_first; static int objs(filestring, name, lib, nperline, initial_nfiles, f_separator, l_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 *f_separator; /* File separator (on a line) */ char *l_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 "l_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, f_separator, l_separator, TRUE); while (*lib != NULL) { /* Do all libraries for opsys */ if ((libtext = syvalue(*lib)) != NULL) { wp = objexpand(libtext, wp, nperline, f_separator, l_separator, FALSE); } lib++; } sysave(name, work, 0); return(obj_nfiles > nperline); } static char * objexpand(string, buffer, nperline, f_separator, l_separator, forcefiletype) char *string; /* Where it comes from */ char *buffer; /* Where it goes to */ int nperline; /* Files per line */ char *f_separator; /* Between files string */ char *l_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()", string); 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 { nptr = ((obj_nfiles % nperline) != 0) ? f_separator : l_separator; while (*nptr != EOS) *b++ = *nptr++; } /* * c has the first byte of the new object file, * copy the file name to the buffer. */ if (opsys == UNIX) { /* * Just copy the string. filetype is set by caller */ while (!iswhite(c) && c != EOS) { *b++ = c; c = *s++; } } else { inacct = FALSE; /* Not in [...] */ skipit = 0; /* Not at ".ext" */ while (!iswhite(c) && c != EOS && (c != ',' || inacct > 0)) { if (c == '(' || c == '[') inacct++; else if (c == ']' || c == ')') inacct--; else if (!inacct && forcefiletype && c == '.') skipit = TRUE; /* no ".ext;1" */ 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); }