home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i055: Library for Purdue University Computing Center tools, Part01/02
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 62517344 5cc85733 e878b79d ecdcfd69
-
- Submitted-by: Kevin Braunsdorf <ksb@cc.purdue.edu>
- Posting-number: Volume 24, Issue 55
- Archive-name: pucc-lib/part01
-
- This two part archive contains the libraries that most of the PUCC
- (Purdue University Computing Center) tools require to compile. You'll
- need to build these to compile any of the nifty stuff that follows.
- Included are:
- libopt(3l) - process a command line
- maketd(1l) - edit a makefile to update transitive dependencies
- srtunq(3l) - in memory string sorting
- -- ksb
-
-
- #!/bin/sh
- # This is pucc-1a, a shell archive (produced by shar 3.49)
- # To extract the files from this archive, save it to a file, remove
- # everything above the "!/bin/sh" line above, and type "sh file_name".
- #
- # made 11/29/1990 15:57 UTC by ksb@cc.purdue.edu (Kevin Braunsdorf)
- # Source directory /ksb/c.s.u-2
- #
- # existing files will NOT be overwritten unless -c is specified
- #
- # This shar contains:
- # length mode name
- # ------ ---------- ------------------------------------------
- # 1321 -rw-r--r-- INSTALL.01
- # 21424 -r--r--r-- maketd/maketd.c
- # 8481 -r--r--r-- maketd/maketd.1l
- # 4616 -r--r--r-- libopt/libopt.3l
- # 5705 -r--r--r-- libsrtunq/libsrtunq.3l
- # 4905 -r--r--r-- maketd/abrv.c
- # 2814 -r--r--r-- libopt/envopt.c
- # 4235 -r--r--r-- maketd/main.c
- # 3826 -r--r--r-- maketd/M4.patch
- # 1360 -rw-r--r-- libopt/Makefile
- # 619 -rw-r--r-- libopt/README
- # 1999 -r--r--r-- libopt/getopt.c
- # 2793 -rw-r--r-- libsrtunq/Makefile
- # 2530 -r--r--r-- libsrtunq/srtdel.c
- # 2731 -rw-r--r-- maketd/Makefile
- # 2359 -r--r--r-- maketd/errors.c
- # 1514 -r--r--r-- libsrtunq/srtapply.c
- # 1452 -r--r--r-- libsrtunq/srtgets.c
- # 1723 -r--r--r-- libsrtunq/srtin.c
- # 1226 -r--r--r-- libsrtunq/srtdtree.c
- # 1240 -r--r--r-- libsrtunq/srtmem.c
- # 1278 -rw-r--r-- maketd/machine.h
- # 1148 -r--r--r-- libopt/getopt.h
- # 1067 -r--r--r-- libsrtunq/srtfree.c
- # 1067 -r--r--r-- libsrtunq/srtgti.c
- # 1011 -r--r--r-- libsrtunq/srtinit.c
- # 1144 -r--r--r-- maketd/maketd.h
- # 819 -r--r--r-- libsrtunq/srtunq.h
- # 621 -r--r--r-- maketd/abrv.h
- # 519 -r--r--r-- libopt/getarg.c
- # 490 -r--r--r-- libsrtunq/README
- # 471 -r--r--r-- maketd/GCC.awk
- # 310 -r--r--r-- maketd/errors.h
- # 256 -r--r--r-- libopt/rescan.c
- # 245 -r--r--r-- maketd/README
- # 216 -r--r--r-- maketd/main.h
- #
- # ============= INSTALL.01 ==============
- if test -f 'INSTALL.01' -a X"$1" != X"-c"; then
- echo 'x - skipping INSTALL.01 (File already exists)'
- else
- echo 'x - extracting INSTALL.01 (Text)'
- sed 's/^X//' << 'Purdue' > 'INSTALL.01' &&
- Contains:
- X libopt(3l) - process a command line
- X maketd(1l) - edit a makefile to update transitive dependencies
- X srtunq(3l) - in memory string sorting
- X
- X
- Notes on depends:
- X - libopt.a and libsrtunq.a need not be installed, but it
- X would make life easier if you want other PUCC tools.
- X
- X - maketd needs libopt.a and libsrtunq.a to compile
- X
- X
- To install these tools:
- X
- 0\ read the manual pages, see if you want any of them
- X
- 1\ vi libopt/Makefile and set DEFS if we do not have strchr/strrchr
- X vi libopt/Makefile
- X
- 2\ build libopt and libsrtunq, ranlib them if you have to
- X (cd libopt && make)
- X (cd libsrtunq && make)
- X
- X ranlib libopt/libopt.a libsrtunq/libsrtunq.a
- X
- 3\ decide where to install all this stuff, change the destinations in
- X the Makefiles {BIN,LIB,ETC,HEADER}
- X vi */Makefile
- X
- 4\ install libopt and libsrtunq if you decided to
- X su
- X (cd libopt && make install)
- X (cd libsrtunq && make install)
- X exit
- X
- 4\ build maketd
- X (cd maketd && make)
- X
- 5\ install maketd
- X su root
- X (cd maketd && make install)
- X exit
- X
- 6\ clean up the dirs
- X (cd libopt && make clean)
- X (cd libsrtunq && make clean)
- X (cd maketd && make clean)
- X
- 7\ if you have mkcat install any manual pages you want
- X su root
- X mkcat -v maketd/maketd.1l libopt/libopt.3l libsrtunq/srtunq.3l
- X exit
- X
- kayessbee
- --
- Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb
- Purdue
- chmod 0644 INSTALL.01 ||
- echo 'restore of INSTALL.01 failed'
- Wc_c="`wc -c < 'INSTALL.01'`"
- test 1321 -eq "$Wc_c" ||
- echo 'INSTALL.01: original size 1321, current size' "$Wc_c"
- fi
- # ============= maketd/maketd.c ==============
- if test ! -d 'maketd'; then
- echo 'x - creating directory maketd'
- mkdir 'maketd'
- fi
- if test -f 'maketd/maketd.c' -a X"$1" != X"-c"; then
- echo 'x - skipping maketd/maketd.c (File already exists)'
- else
- echo 'x - extracting maketd/maketd.c (Text)'
- sed 's/^X//' << 'Purdue' > 'maketd/maketd.c' &&
- /*
- X * the real brains are in this file
- X */
- #include "machine.h"
- X
- #include <stdio.h>
- #include <sys/types.h>
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <ctype.h>
- #if defined(SYSV)
- #include <string.h>
- #include "bsd.h"
- #else
- #include <strings.h>
- #endif
- X
- extern FILE *popen();
- extern int errno;
- extern char *sys_errlist[];
- #define strerror(Me) (sys_errlist[Me])
- X
- #include "main.h"
- #include "maketd.h"
- #include "srtunq.h"
- #include "abrv.h"
- #include "errors.h"
- X
- #if !defined(F_OK)
- #define F_OK 0
- #endif
- X
- /*
- X * if your cpp doesn't grok -M use something like this...
- X * "/lib/cpp -E %I %F |sed -n 's@^# *[0-9]* *"\\(.*\\)"@%f: \\1@p'"
- X * to format the lines into `file.o: file.d'
- X * Otherwise use:
- X * "/lib/cpp -M %I %F",
- X * the line for gcc's cpp is not so short, but it can be done.
- X * (See GCC.awk for a description, and some clues.)
- X */
- X
- char *preprocessors[] = {
- #if defined(CPP)
- X CPP,
- #else
- #if defined(CPP_M)
- X "/lib/cpp -M %I %F",
- #else
- X /* once for C, once for expand, once for sed */
- X "/lib/cpp -E %I %F |sed -n 's@^# *[0-9]* *\"\\\\(.*\\\\)\"@%f: \\\\1@p'",
- #endif
- #endif
- X
- #if defined(M4)
- X M4
- #else
- X "/usr/bin/m4 -M %F"
- #endif
- };
- X
- char
- X *pchBackup; /* the backup file name */
- X
- FILE *makefp; /* file pointer to the dest makefile */
- int
- X backedup = FALSE; /* is the backup file is present */
- X
- static struct srtent
- X incld;
- static DependInfo
- X FileInfo = { /* our template for all files */
- X 0, 0,
- X NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
- X (DependInfo *)0
- X };
- static FILE
- X *fpBackup, /* file pointer to the backup file */
- X *fpPipe; /* pipe file pointer for preproc */
- static char
- X sbInc[] =
- #if defined(INCLD)
- X INCLD,
- #else
- X "/usr/include",
- #endif
- X deplin[] =
- X "# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT\n",
- X searchdep[] =
- X "# DO NOT DELETE THIS LINE",
- X trailer[] =
- X "\n# *** Do not add anything here - It will go away. ***\n";
- X
- /* SetPP
- X * This routine changes the preprocessor to be used on the next filename.
- X * It has one argument (i) that is the number of the preprocessor to use
- X * 0 == /lib/cpp
- X * 1 == /usr/bin/m4
- X */
- int
- SetPP(i)
- int i;
- {
- X FileInfo.preprocessor = preprocessors[i];
- }
- X
- /* user filter
- X * This routine allows the user to scan anything he can code a program
- X * (script?) to produce `file.z: dep.x' lines on std for, like
- X *
- X * /lib/cpp -E %I %F | sed -n 's/^# *[0-9]* *"\(.*\)"/%f: \1/p'
- X */
- int
- UserFilter(pcFilter)
- char *pcFilter;
- {
- X if ((char *)0 == pcFilter || '\000' != pcFilter[0])
- X FileInfo.preprocessor = pcFilter;
- X else
- X FileInfo.preprocessor = (char *)0;
- }
- X
- X
- /* SetSuffix
- X * This routine changes the suffix to add to the next file that is processed.
- X * If binary is set, it goes into binary mode. The only way to unset binary
- X * mode is to set a new suffix.
- X */
- int
- SetSuffix(option, suffix)
- int option;
- char *suffix;
- {
- X if ('b' == option) {
- X FileInfo.binarydep = 1;
- X } else {
- X FileInfo.suffix = STRSAVE(suffix);
- X FileInfo.binarydep = 0;
- X }
- }
- X
- /* SetLocalO
- X * Hey, what more can I say, this sets the local-o and the non-local o
- X * options in the file structure.
- X */
- int
- SetLocalO(i)
- int i;
- {
- X FileInfo.localo = i;
- }
- X
- /* SetCPPFlags
- X * This function sets the CPP flags. It is given two arguments, the
- X * option (CDIU), and the argument given. If the option is C, it
- X * clears the previous CPP flags. Otherwise, it just catentiates a
- X * string of options.
- X */
- int
- SetCPPFlags(option, argument)
- int option;
- char *argument;
- {
- X register char *pch = NULL;
- X register unsigned len;
- X static char sbOption[4] = " -?";
- X extern char *malloc(), *realloc();
- X
- X if ('C' == option) {
- X if (NULL != FileInfo.cppflags) {
- X free(FileInfo.cppflags);
- X FileInfo.cppflags = NULL;
- X }
- X return ;
- X }
- X pch = FileInfo.cppflags;
- X len = strlen(argument)+4;
- X if (NULL == pch) {
- X FileInfo.cppflags = malloc(len);
- X FileInfo.cppflags[0] = '\000';
- X } else {
- X len += strlen(pch);
- X FileInfo.cppflags = realloc(FileInfo.cppflags, len);
- X }
- X sbOption[2] = option;
- X strcat(FileInfo.cppflags, sbOption);
- X strcat(FileInfo.cppflags, argument);
- X
- X /* insert -I files includes into abbreviation list
- X */
- X if ('I' == option) {
- X /* if we end in '/' take it off */
- X pch = strrchr(argument, '/');
- X if ((char *)0 != pch && '\000' == pch[1])
- X pch[1] = '\000';
- X if (NULL == srtin(&abrv, hincl(argument), lngsrt)) {
- X OutOfMemory();
- X }
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: inserted abbr %s\n", progname, argument);
- X }
- }
- X
- /* SetObjPath
- X * tell processing part about non-local dot-o's
- X */
- int
- SetObjPath(destdir)
- char *destdir;
- {
- X FileInfo.destdir = '.' == FileInfo.destdir[0] && '\000' == FileInfo.destdir ? NULL : STRSAVE(destdir);
- }
- X
- /* SetTargetName
- X * we don't ned to string save it because only one file can use it, and
- X * it will string save it.
- X */
- int
- SetTargetName(basename)
- char *basename;
- {
- X FileInfo.basename = basename;
- }
- X
- int
- FileArgs(filename)
- char *filename;
- {
- X register DependInfo *pDI = &FileInfo;
- X
- X while (NULL != pDI->next)
- X pDI = pDI->next;
- X pDI->next = (DependInfo *)malloc((unsigned)sizeof(DependInfo));
- X pDI = pDI->next;
- X pDI->localo = FileInfo.localo;
- X pDI->binarydep = FileInfo.binarydep;
- X pDI->filename = STRSAVE(filename);
- X pDI->inlib = inlib;
- X
- X if (FileInfo.preprocessor)
- X pDI->preprocessor = FileInfo.preprocessor;
- X else
- X pDI->preprocessor = preprocessors[0];
- X
- X pDI->explicit = explicit; /* from main.c parser */
- X
- X pDI->cppflags = pDI->destdir = pDI->suffix = pDI->basename = (char *)0;
- X if (NULL != FileInfo.cppflags)
- X pDI->cppflags = STRSAVE(FileInfo.cppflags);
- X if (NULL != FileInfo.destdir)
- X pDI->destdir = STRSAVE(FileInfo.destdir);
- X if (NULL != FileInfo.suffix)
- X pDI->suffix = STRSAVE(FileInfo.suffix);
- X if (NULL != FileInfo.basename)
- X pDI->basename = STRSAVE(FileInfo.basename);
- X pDI->next = NULL;
- X FileInfo.basename = NULL;
- }
- X
- /* BackUp
- X * Back up the makefile into the backup makefile.
- X */
- void
- BackUp()
- {
- X register unsigned len;
- X if (NULL == exten) {
- X exten = STRSAVE(".bak");
- X }
- X
- X len = strlen(makename)+strlen(exten)+2;
- X pchBackup = malloc(len);
- X strcpy(pchBackup, makename);
- X if ('.' != *exten) {
- X strcat(pchBackup, ".");
- X }
- X strcat(pchBackup, exten);
- X
- X /* Remove the old backup file */
- X if (0 == access(pchBackup, F_OK) && 0 != unlink(pchBackup)) {
- X fprintf(stderr, "%s: unlink: %s: %s\n", progname, pchBackup, strerror(errno));
- X exit(3);
- X }
- X
- X /* Move current makefile to backup file */
- X if (0 != link(makename, pchBackup)) {
- X fprintf(stderr, "%s: link: %s to %s: %s\n", progname, makename, pchBackup, strerror(errno));
- X exit(4);
- X }
- X
- X backedup = TRUE;
- X if (0 != unlink(makename)) {
- X fprintf(stderr, "%s: unlink: %s: %s\n", progname, makename, strerror(errno));
- X RestoreFiles();
- X }
- }
- X
- /* DestName
- X * Given the info about the file, figure out what the destination name
- X * should be on the dependancy line.
- X */
- char *
- DestName(file)
- DependInfo *file;
- {
- X static char buf[BUFSIZE];
- X register char *pch = NULL;
- X
- X /* find a prefix:
- X * the -o (destdir) flag has precedence over the -n or -l flags;
- X * then the non-local o option;
- X * else we don't want one
- X */
- X if (NULL != file->destdir) {
- X strcpy(buf, file->destdir);
- X pch = strrchr(buf, '\000');
- X if ('/' != *--pch) {
- X *++pch = '/';
- X *++pch = '\000';
- X }
- X } else if (FALSE != file->localo) {
- X strcpy(buf, file->filename);
- X if (NULL != (pch = strrchr(buf, '/'))) {
- X pch[1] = '\000';
- X }
- X } else {
- X buf[0] = '\000';
- X }
- X
- X /* find a basename
- X * when they supplied the basename, trust them
- X * else strip off any leading pathname to the file and save it in buf
- X * (but get rid of the suffix too)
- X * thus buf contains only the basename
- X */
- X if (NULL != file->basename) {
- X strcat(buf, file->basename);
- X } else {
- X if (NULL == (pch = strrchr(file->filename, '/'))) {
- X pch = file->filename;
- X } else {
- X ++pch;
- X }
- X strcat(buf, pch);
- X if (NULL != (pch = strrchr(buf, '.'))) {
- X *pch = '\000';
- X }
- X }
- X
- X /* if this is not a binary dependancy, add a suffix to it
- X */
- X if (1 != file->binarydep) {
- X if (NULL != file->suffix) {
- X strcat(buf, file->suffix);
- X } else {
- X strcat(buf, ".o");
- X }
- X }
- X
- X return buf;
- }
- X
- /* DoReplace
- X * This is a routine that goes through the current dependancies (if any)
- X * and spits out the ones that are NOT being replaced. If the shortening
- X * of include file names is turned off, it will spit out the currently
- X * defined vars, otherwise, it lets them be rebuilt.
- X */
- void
- DoReplace()
- {
- X register DependInfo *pDI;
- X register int found = FALSE, cont = FALSE;
- X register char *fname;
- X register int len;
- X auto char buf[BUFSIZE];
- X
- X while (NULL != fgets(buf, BUFSIZE, fpBackup)) {
- X if (FALSE != cont) {
- X if (FALSE == found) {
- X fputs(buf, makefp);
- X }
- X cont = '\\' == buf[strlen(buf) - 2] ? TRUE : FALSE;
- X continue;
- X }
- X
- X found = cont = FALSE;
- X if ('\n' == buf[0]) {
- X continue;
- X }
- X
- X /* If we are not shortening the include file names on this
- X * replacement, we at least have to spit out the old
- X * abbreviations
- X */
- X if (isupper(buf[0]) && '=' == buf[1]) {
- X fname = strrchr(buf, '\n');
- X if ((char *)0 == fname) {
- X fprintf(stderr, "%s: internal error or line too long\n", progname);
- X RestoreFiles();
- X }
- X *fname = '\000';
- X if (NULL == srtin(&abrv, hincl(buf+2), lngsrt)) {
- X OutOfMemory();
- X }
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: inserted abbr %s\n", progname, buf+2);
- X } else {
- X for (pDI = FileInfo.next; NULL != pDI; pDI = pDI->next) {
- X fname = DestName(pDI);
- X len = strlen(fname);
- X found = (':' == buf[len] &&
- X 0 == strncmp(fname, buf, len))? TRUE: FALSE;
- X if (found)
- X break;
- X }
- X if (FALSE == found && '#' != buf[0]) {
- X fputc('\n', makefp);
- X fputs(buf, makefp);
- X }
- X cont = '\\' == buf[strlen(buf) - 2] ? TRUE : FALSE;
- X }
- X }
- }
- X
- /*
- X * output a user rule expanded (ksb)
- X */
- void
- expand(src, pDI, fpTo)
- char *src;
- DependInfo *pDI;
- FILE *fpTo;
- {
- X register int i, num;
- X register char chLast = '\n';
- X register char *pc;
- X auto char acf[1025];
- X auto char acF[1025];
- X auto char
- X *tp, /* the / in %o/%t%s */
- X *sp, /* the . in %s, or a "\000" */
- X *Tp, /* the / in %o/%t%s */
- X *Sp; /* the . in %s, or a "\000" */
- X
- X pc = strrchr(pDI->filename, '/');
- X if ((char *)0 == pc) {
- X strcpy(acf, ".");
- X strcpy(acF, ".");
- X } else {
- X *pc = '\000';
- X strcpy(acf, pDI->filename);
- X strcpy(acF, pDI->filename);
- X *pc = '/';
- X }
- X if ((char *)0 != pDI->destdir) {
- X strcpy(acf, pDI->destdir);
- X }
- X
- X tp = strrchr(acf, '\000');
- X tp[0] = '/';
- X Tp = strrchr(acF, '\000');
- X Tp[0] = '/';
- X if ((char *)0 == pc) {
- X strcpy(tp+1, pDI->filename);
- X strcpy(Tp+1, pDI->filename);
- X } else {
- X strcpy(tp+1, pc+1);
- X strcpy(Tp+1, pc+1);
- X }
- X if ((char *)0 != pDI->basename) {
- X strcpy(tp+1, pDI->basename);
- X }
- X
- X sp = strrchr(tp, '.');
- X if ((char *)0 == sp)
- X sp = strrchr(tp, '\000');
- X Sp = strrchr(Tp, '.');
- X
- X if ((char *)0 != pDI->suffix) {
- X strcpy(sp, pDI->suffix);
- X } else if (1 == pDI->binarydep) {
- X sp[0] = '\000';
- X } else {
- X strcpy(sp, ".o");
- X }
- X
- X while (*src) {
- X if ('\n' == chLast) {
- X if (makefp == fpTo) /* ZZZ hack */
- X putc('\t', fpTo);
- X }
- X chLast = *src;
- X switch (*src) {
- X case '%':
- X /* %f: %F
- X * %o/%t.%s: %O/%T.%S
- X * %%
- X */
- X switch (*++src) {
- X /* target */
- X case 'o': /* directory part */
- X *tp = '\000';
- X fputs(acf, fpTo);
- X *tp = '/';
- X break;
- X
- X case 't':
- X if ('\000' == *sp) {
- X fputs(tp+1, fpTo);
- X } else {
- X i = *sp;
- X *sp = '\000';
- X fputs(tp+1, fpTo);
- X *sp = i;
- X }
- X break;
- X
- X case 's':
- X fputs(sp, fpTo);
- X break;
- X
- X case 'f':
- X fputs(acf, fpTo);
- X break;
- X
- X /* source */
- X case 'O':
- X *Tp = '\000';
- X fputs(acF, fpTo);
- X *Tp = '/';
- X break;
- X
- X case 'T':
- X if ((char *)0 == Sp) {
- X fputs(Tp+1, fpTo);
- X } else {
- X *Sp = '\000';
- X fputs(Tp+1, fpTo);
- X *Sp = '.';
- X }
- X break;
- X
- X case 'S':
- X if ((char *)0 != Sp)
- X fputs(Sp, fpTo);
- X break;
- X
- X case 'F':
- X fputs(acF, fpTo);
- X break;
- X
- X /* global */
- X case 'L':
- X if ((char *)0 != pDI->inlib)
- X fputs(pDI->inlib, fpTo);
- X break;
- X
- X case 'I':
- X if ((char *)0 != pDI->cppflags)
- X fputs(pDI->cppflags, fpTo);
- X break;
- X
- X case '%':
- X default: /* unrecognized chars are copied thru */
- X fputc(*src, fpTo);
- X break;
- X }
- X src++;
- X break;
- X
- X case '\\':
- X switch (*++src) {
- X case '\n': /* how would this happen? */
- X ++src;
- X break;
- X case 'a':
- X fputc('\007', fpTo);
- X ++src;
- X break;
- X case 'n': /* newline */
- X fputc('\n', fpTo);
- X chLast = '\n';
- X ++src;
- X break;
- X case 't':
- X fputc('\t', fpTo);
- X ++src;
- X break;
- X case 'b':
- X fputc('\b', fpTo);
- X ++src;
- X break;
- X case 'r':
- X fputc('\r', fpTo);
- X ++src;
- X break;
- X case 'f':
- X fputc('\f', fpTo);
- X ++src;
- X break;
- X case 'v':
- X fputc('\013', fpTo);
- X ++src;
- X break;
- X case '\\':
- X ++src;
- X case '\000':
- X fputc('\\', fpTo);
- X break;
- X
- X case '0': case '1': case '2': case '3':
- X case '4': case '5': case '6': case '7':
- X num = *src++ - '0';
- X for (i = 0; i < 2; i++) {
- X if (! isdigit(*src)) {
- X break;
- X }
- X num <<= 3;
- X num += *src++ - '0';
- X }
- X fputc(num, fpTo);
- X chLast = num;
- X break;
- X case '8': case '9':
- X /* 8 & 9 are bogus octals,
- X * cc makes them literals
- X */
- X /*fallthrough*/
- X default:
- X fputc(*src++, fpTo);
- X break;
- X }
- X break;
- X default:
- X fputc(*src, fpTo);
- X src++;
- X break;
- X }
- X }
- X
- X if ('\n' != chLast)
- X fputc('\n', fpTo);
- }
- X
- /* generate the depend info for a given file
- X */
- void
- DoDepend(file)
- DependInfo *file;
- {
- X register int lineend, i;
- X register char *p, *q, *name;
- X auto int complen;
- X auto char ppbuf[BUFSIZE], buf[BUFSIZE];
- X auto char acFile[1025];
- X auto FILE *fpCmd;
- X
- X /* compute the dest name and save it, we want this one for a while
- X */
- X name = DestName(file);
- X name = STRSAVE(name);
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: working on %s\n", progname, name);
- X
- X /* with the help of a little conditional compilation
- X * set up the command string
- X */
- X mktemp(strcpy(acFile, "/tmp/mtdXXXXXX"));
- X if (NULL == (fpCmd = fopen(acFile, "w"))) {
- X fprintf(stderr, "%s: fopen: %s: %s\n", progname, acFile, strerror(errno));
- X RestoreFiles();
- X }
- X expand(file->preprocessor, file, fpCmd);
- X fclose(fpCmd);
- X
- X if (FALSE != verbose) {
- X fprintf(stderr, "%s: shell command: (in %s)\n", progname, acFile);
- X sprintf(buf, "cat %s", acFile);
- X system(buf);
- X }
- X
- X (void)sprintf(buf, "sh <%s", acFile);
- X if (NULL == (fpPipe = popen(buf, "r"))) {
- X fprintf(stderr, "%s: popen: %s: %s\n", progname, buf, strerror(errno));
- X RestoreFiles();
- X }
- X
- X /* Start with a fresh list of dependancy files */
- X srtfree(&incld);
- X
- X while (NULL != fgets(ppbuf, BUFSIZE, fpPipe)) {
- X if (NULL == (p = strchr(ppbuf, ':'))) {
- X fprintf(stderr, "%s: preprocessor output missing colon\n", progname);
- X RestoreFiles();
- X }
- X ++p; /* Get past colon */
- X if (' ' != *p++) {
- X fprintf(stderr, "%s: preprocessor output missing space\n", progname);
- X RestoreFiles();
- X }
- X
- X /* Make pathname pretty */
- X p = hincl(p);
- X
- X /* Replace newline with a null */
- X if (NULL != (q = strchr(p, '\n')))
- X *q = '\000';
- X
- X /* If all dependancies are NOT to be made, skip over
- X * the basic include path
- X */
- X if (FALSE == alldep && 0 == strncmp(sbInc, p, sizeof(sbInc)-1))
- X continue;
- X
- X /* Insert it into our list */
- X if (NULL == srtin(&incld, p, strcmp)) {
- X OutOfMemory();
- X }
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: inserted %s\n", progname, p);
- X }
- #if 0
- X while (NULL != fgets(ppbuf, BUFSIZE, fpPipe)) {
- X /* An include statement starts with a # */
- X if ('#' != ppbuf[0])
- X continue;
- X
- X /* eat #ident lines (mostly a sysv thing) */
- X p = ppbuf;
- X do {
- X ++p;
- X } while (' ' == *p || '\t' == *p);
- X if (! isdigit(*p)) {
- X continue;
- X }
- X
- X /* Find the first double quote and go one past it */
- X if (NULL == (p = strchr(p, '"')))
- X continue;
- X ++p;
- X
- X /* Make the path pretty */
- X p = hincl(p);
- X
- X if (NULL != (q = strchr(p, '"')))
- X *q = '\000';
- X
- X /* If all dependancies are NOT to be made, skip over
- X * the basic include path
- X */
- X if (FALSE == alldep && 0 == strncmp(sbInc, p, sizeof(sbInc)-1))
- X continue;
- X
- X /* Insert it into our list */
- X if (NULL == srtin(&incld, p, strcmp))
- X OutOfMemory();
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: inserted %s\n", progname, p);
- X }
- #endif /* need to look at raw cpp output */
- X
- X /* Initialize so we can use srtgets */
- X srtgti(&incld);
- X
- X lineend = MAXCOL+1; /* Force a newline in the output */
- X /* Write out the entries */
- X while (NULL != (p = srtgets(&incld))) {
- X /* set i = found index or MXABR */
- X if (FALSE != shortincl && MXABR != (i = findabr(p))) {
- X p += abrvlen[i];
- X if ('/' != p[0] && '\000' != p[0]) {
- X complen = 4;
- X } else {
- X complen = 2;
- X }
- X } else {
- X complen = 0;
- X }
- X
- X complen += strlen(p);
- X if (MAXCOL <= lineend + complen) {
- X if ((char *)0 != name) {
- X /* 2 for the colon and space */
- X lineend = strlen(name) + 2;
- X if ((char *)0 != file->inlib) {
- X /* + parens and lib name */
- X lineend += 2 + strlen(file->inlib);
- X fprintf(makefp, "\n%s(%s): ", file->inlib, name);
- X } else {
- X fprintf(makefp, "\n%s: ", name);
- X }
- X free(name);
- X name = (char *) 0;
- X if (MAXCOL <= lineend + complen) {
- X lineend = 8;
- X fprintf(makefp, "\\\n\t");
- X }
- X } else {
- X lineend = 8;
- X fprintf(makefp, " \\\n\t");
- X }
- X } else {
- X ++lineend;
- X fputc(' ', makefp);
- X }
- X
- X if (FALSE != shortincl && MXABR != i) {
- X if ('/' != p[0] && '\000' != p[0]) {
- X fprintf(makefp, "${%c}", 'A' + i);
- X } else {
- X fprintf(makefp, "$%c", 'A' + i);
- X }
- X }
- X fputs(p, makefp);
- X lineend += complen;
- X }
- X fputc('\n', makefp);
- X pclose(fpPipe);
- X (void)unlink(acFile);
- X if ((char *)0 != file->explicit) {
- X expand(file->explicit, file, makefp);
- X }
- }
- X
- /* DoInit
- X * Initialize the signal catching routines
- X * and abreviation list
- X */
- int
- DoInit()
- {
- X init_sigs();
- X srtinit(&abrv);
- }
- X
- /* MakeTD
- X * This part is the actual work-horse of the program. All of the options
- X * have been processed at this point, and all we have to do is interpret
- X * their meanings
- X */
- int
- MakeTD()
- {
- X register DependInfo *pDI;
- X register int fCont;
- X register char *pchTemp;
- X auto char sbLine[BUFSIZE];
- X auto struct stat stOld;
- X
- X /* Find out which makefile is to be used. First, if the user
- X * specifies a makefile, use that. If he doesn't, check and
- X * see if 'makefile' exists. Finally, if that doesn't check
- X * out, see if 'Makefile' exists.
- X */
- X if (NULL == makename) {
- X makename = STRSAVE("makefile");
- X if (0 != access(makename, F_OK)) {
- X makename[0] = 'M';
- X if (0 != access(makename, F_OK)) {
- X fprintf(stderr, "%s: cannot find makefile\n", progname);
- X exit(1);
- X }
- X }
- X } else {
- X if (0 != access(makename, F_OK)) {
- X fprintf(stderr, "%s: access: %s: %s\n", progname, makename, strerror(errno));
- X exit(1);
- X }
- X }
- X
- X /* Now backup the makefile to a backup file and unlink the current one
- X */
- X if (FALSE == use_stdout) {
- X BackUp();
- X } else {
- X pchBackup = makename;
- X }
- X stat(pchBackup, &stOld);
- X
- X /* Now open the destination makefile, copy over all of the current
- X * makefile up to the '# DO NOT DELETE THIS LINE' line (or the
- X * end-of-file, whichever comes first), and then continue with
- X * processing.
- X */
- X if (NULL == (fpBackup = fopen(pchBackup, "r"))) {
- X fprintf(stderr, "%s: fopen: %s: %s\n", progname, pchBackup, strerror(errno));
- X RestoreFiles();
- X }
- X
- X if (FALSE != use_stdout) {
- X makefp = stdout;
- X } else if (NULL == (makefp = fopen(makename, "w"))) {
- X fprintf(stderr, "%s fopen: %s: %s\n", progname, makename, strerror(errno));
- X RestoreFiles();
- X } else {
- X /* chmod the Makefile */
- X if (-1 == chmod(makename, (stOld.st_mode & 07777))) {
- X fprintf(stderr, "%s: chmod: %s: %s\n", progname, makename, strerror(errno));
- X RestoreFiles();
- X }
- X }
- X
- X /* clever use of continuations used to hose us over
- X */
- X fCont = FALSE;
- X while (NULL != fgets(sbLine, BUFSIZE, fpBackup) && (FALSE != fCont ||
- X 0 != strncmp(searchdep, sbLine, strlen(searchdep)))) {
- X pchTemp = strrchr(sbLine, '\\');
- X if ((char *)0 != pchTemp && '\n' == pchTemp[1]) {
- X fCont = TRUE;
- X } else {
- X if (FALSE == fCont)
- X srchincl(sbLine);
- X
- X fCont = FALSE;
- X }
- X if (FALSE == use_stdout)
- X (void)fputs(sbLine, makefp);
- X }
- X
- X /* If we need the header put in, do it now
- X */
- X if (FALSE == use_stdout || FALSE != force_head) {
- X (void)fputs(deplin, makefp);
- X }
- X
- X /* Put out the abbreviations table
- X */
- X if (FALSE != alldep) {
- X sprintf(sbLine, "%s/sys", sbInc);
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: all depends inserts %s and %s\n", progname, sbInc, sbLine);
- X if (NULL == srtin(&abrv, hincl(sbInc), lngsrt) ||
- X NULL == srtin(&abrv, hincl(sbLine), lngsrt)) {
- X OutOfMemory();
- X }
- X }
- X
- X if (FALSE != shortincl) {
- X abrvsetup();
- X }
- X
- X /* Check to see if we have to replace the files instead of just
- X * recreating all dependancies
- X */
- X if (FALSE != replace && FALSE == use_stdout) {
- X DoReplace();
- X }
- X
- X /* Now, after we have done everything that needs to be done except
- X * putting out the dependancies for the list of files we have, lets
- X * go ahead and do that! First we have to initialize our sorted
- X * list.
- X */
- X srtinit(&incld); /* Initialize sorted list of files */
- X for (pDI = FileInfo.next ; NULL != pDI; pDI = pDI->next) {
- X DoDepend(pDI);
- X }
- X
- X /* Put out the trailer if needed
- X */
- X if (FALSE == use_stdout || FALSE != force_head) {
- X fputs(trailer, makefp);
- X }
- X
- #ifdef DEL_BACKUP
- X if (FALSE != backedup && 0 != unlink(backupfn)) {
- X fprintf(stderr, "%s: unlink: %s: %s\n", progname, pchBackup, strerror(errno));
- X exit(1);
- X }
- #endif /* DEL_BACKUP */
- X exit(0);
- }
- Purdue
- chmod 0444 maketd/maketd.c ||
- echo 'restore of maketd/maketd.c failed'
- Wc_c="`wc -c < 'maketd/maketd.c'`"
- test 21424 -eq "$Wc_c" ||
- echo 'maketd/maketd.c: original size 21424, current size' "$Wc_c"
- fi
- # ============= maketd/maketd.1l ==============
- if test -f 'maketd/maketd.1l' -a X"$1" != X"-c"; then
- echo 'x - skipping maketd/maketd.1l (File already exists)'
- else
- echo 'x - extracting maketd/maketd.1l (Text)'
- sed 's/^X//' << 'Purdue' > 'maketd/maketd.1l' &&
- .\" by Kevin Braunsdorf
- .\" $Laser: tbl %f | ltroff -man
- .TH MAKETD 1L PUCC
- .SH NAME
- maketd \- edit a makefile to update transitive dependencies
- .SH SYNOPSIS
- \fBmaketd\fP [\-\fB4CabcdfhlnrvVx\fP] [\-\fBD\fP \fIdefine\fP] [\-\fBL\fP \fIlib.a\fP] [\-\fBI\fP \fIincludedir\fP] [\-\fBU\fP \fIundefine\fP] [\-\fBj\fP \fIextender\fP] [\-\fBm\fP \fImakefile\fP] [\-\fBo\fP \fIdir\fP] [\-\fBs\fP \fIsuffix\fP] [\-\fBt\fP \fItarget\fP] [\fBfiles\fP]
- .SH DESCRIPTION
- .B Maketd
- computes dependencies for targets that are introduced through the
- C preprocessor's (cpp) \fI#include\fP directive.
- The development of this program resulted from
- .IR make ( 1 )'s
- inability to recognize transitive dependencies. For example,
- given the following makefile fragment:
- .sp 1
- X xx.o: xx.c e.h
- .sp 1
- X e.h: struct.h /usr/include/local/const.h
- .sp 1
- \fIMake\fP will not recognize the target xx.o's dependency on struct.h.
- \fIMaketd\fP generates lines like:
- .sp 1
- X xx.o: xx.c e.h struct.h $L/const.h
- .sp 1
- Thus making the target xx.o not only dependent on all files that it includes,
- but also recursively on all files that the included files include.
- This is achieved by passing the source through the C preprocessor
- (\fI/bin/cc\fP \-\fIM\fP).
- .PP
- The directories used in the search for include files
- are identical to the ones used by the C compiler because the
- C preprocessor is used. This also means that
- .IR #define 's,
- .IR #ifdef 's,
- etc., are evaluated.
- It is necessary to recompute the dependencies when any source has been changed.
- The generated dependencies will be inserted after a line of the form
- \*(lq# DO NOT DELETE...\*(rq (which will be inserted if \fBmaketd\fP
- finds the end of file).
- Everything after this line may be deleted or changed as \fBmaketd\fP edits
- the \fImakefile\fP (the portion of the makefile before this line is only
- examined for context).
- If no such line exists, a line of the expected form will be emitted,
- followed by the dependencies.
- .PP
- By default \fBmaketd\fP will search for the \fImakefile\fP
- to be edited in the same way \fImake\fP does; that is by first checking
- for the existence of \*(lqmakefile\*(rq, then \*(lqMakefile\*(rq.
- The \-\fBm\fP and \-\fBd\fP options override this default action (below).
- Before it is edited, \fImakefile\fP will be saved in
- \*(lq\fImakefile\fP.\fIextend\fP\*(rq
- (overwriting any existing file with the same name).
- This \fIextender\fP on the old version of \fImakefile\fP may
- be changed by using the \-\fBj\fP option (below).
- .SH OPTIONS
- .PP
- Options and arguments may be intermixed on the command line to modify
- \fBmaketd\fP's behavior on a per file basis.
- .TP
- .BI \-4
- Use
- .IR m4 ( 1 )
- as the preprocessor rather than
- .IR cc ( 1 ) .
- This requires that modifications have been made to m4 and that
- this program be compiled with CPP_M defined. Use \*(lqmaketd \-h\*(rq
- to check this.
- .TP
- .BI \-a
- Normally, dependencies on files in \*(lq/usr/include\*(rq are
- not included. This option also includes dependencies on those files.
- This option should always be used for system level makefiles.
- .TP
- .BI \-b
- Generate dependencies for binaries rather than object files.
- This is equivalent to specifying a null suffix: the \*(lq.o\*(rq
- is stripped from the target.
- .TP
- .BI \-c
- Use cc to generate dependencies (rather than m4). This is the default.
- .TP
- .BI \-d
- Dependencies are written to standard output instead of editing a makefile.
- The standard header and trailer, \*(lq# DO NOT DELETE...\*(rq are not printed.
- .\".TP
- .\".BI \-e rule
- .\"The given \fIrule\fP is ouptut under each of the following \fIfile\fP's
- .\"dependency lists.
- .\"For \fIprintf\fP-like percent (%) escapes are expanded to allow the
- .\"user to customize the rule.
- .\".sp 1
- .\".RS
- .\".TS
- .\"l l l.
- .\"escape expands
- .\"% a percent
- .\"F the source file
- .\"I the \fIcpp\fP flags for this file
- .\"O the source dir
- .\"S the source suffix
- .\"L the library containing this file
- .\"T the source basename
- .\"f the full target file
- .\"o the target dir (set by \-\fBo\fP)
- .\"s the target suffix (set by \-\fBs\fP)
- .\"t the target base name (set by \-\fBt\fP)
- .\".TE
- .\".RE
- .TP
- .BI \-f
- Force printing of header and trailer.
- Normally these are suppressed when the output file is the standard output.
- .TP
- .BI \-h
- Only output a usage summary.
- .TP
- .BI \-j extender
- Specify an extension for the backup makefile, rather than the default
- \*(lqbak\*(rq extender.
- .TP
- .BI \-l
- Turn off the nonlocal object option, and make all targets local.
- .TP
- .BI \-m makefile
- Instead of editing \*(lqmakefile\*(rq, \fImakefile\fP is edited.
- .TP
- .BI \-n
- Generate nonlocal object dependency paths.
- These paths will match the source paths given.
- .TP
- .BI \-o dir
- Generate nonlocal object dependencies in the specified \fIdir\fP.
- This option generates dependencies of the form
- .sp 1
- X \fIdir\fP/a.o: a.c
- .sp 1
- which is useful for makefiles that produce the objects in
- a separate subdirectory.
- The name of the directory must not be empty (see \-\fBl\fP above).
- .TP
- .BI \-r
- Replace the dependencies for the target(s) mentioned on the command line.
- Do not alter any other dependencies that may have been in \fImakefile\fP.
- This option is of limited use and unlimited misuse: beware.
- .TP
- .BI \-s suffix
- Supply a suffix for the target. The \fIsuffix\fP should
- start with a \*(lq.\*(rq.
- The target file name should have a suffix of some sort that
- is delimited by a \*(lq.\*(rq that is replaced by this suffix.
- .TP
- .BI \-t target
- Supply a new basename for the target rather than using the basename of the
- source file.
- .TP
- .BI \-v
- Be verbose.
- Extra output is directed to the standard error channel.
- .TP
- .BI \-V
- Show which version of \fImaketd\fP is running.
- .TP
- .BI \-x
- Do not shorten include files.
- The pathnames \*(lq/usr/include\*(rq and \*(lq/usr/include/sys\*(rq
- along with any pathnames specified with the \-I options, are abbreviated.
- Unused uppercase single letters are defined in \fImakefile\fP and used to
- compress pathnames.
- .TP
- .BI \-C
- Cancel all previous cpp flags (\-\fBD\fP, \-\fBI\fP, and \-\fBU\fP)
- and begin a new list. This is useful for generating
- dependencies for more than one product with only one \fBmaketd\fP call.
- .TP
- .BI \-D define
- Specify a cpp (C preprocessor) definition. See
- .IR cc ( 1 ).
- for a complete description.
- .\".TP
- .\".BI \-E
- .\"Cancel an explicit \fIrule\fP given by \-\fBe\fP.
- .\".TP
- .\".BI \-F gen-dep
- .\"The \fIgen-dep\fP shell command is expanded as a \-e \fIrule\fP would be
- .\"and given to the shell. The resulting output must look like the
- .\"output of \fIcpp\fP \fI\-M\fP, that is contain only lines of the form:
- .\".sp 1
- .\" \fItarget\fP\fB: \fP\fIdep\fP
- .\".sp 1
- .\"which should list of all the \fIdeps\fP on which \fItarget\fP
- .\"depends one per line.
- .TP
- .BI \-I includedir
- Specify a directory for cpp to search for include files.
- See
- .IR cc ( 1 )
- for a complete description.
- Note that \fIincludedir\fP is subject to abbreviation unless \-\fBx\fP is
- given.
- .TP
- .BI \-L lib.a
- This option produces a dependency that tells \fImake\fP(1) that the
- target is part of \fIlib.a\fP.
- .TP
- .BI \-U name
- Remove any initial definition of the (C preprocessor) variable
- .IR name .
- .SH EXAMPLES
- A typical application in a makefile might look like:
- .sp 1
- .RS
- .nf
- L=/usr/include/local
- INCLUDE= \-I$L \-I../h
- CDEFS= \-DPUCC \-DBSD4_2
- CFLAGS= ${DEFS} ${INCLUDE}
- X
- SRC= a.c b.c c.c
- HDR= a.h b.h c.h
- X
- \&. . .
- depend: ${SRC} ${HDR}
- X maketd \-a ${CDEFS} ${INCLUDE} ${SRC}
- X
- # DO NOT DELETE THIS LINE \- maketd DEPENDS ON IT
- X
- a.o: a.c a.h b.h c.h $L/goop.h
- X
- b.o: b.c b.h $L/goop.h
- X
- c.o: c.c c.h
- X
- # *** Do not add anything here \- It will go away. ***
- .fi
- .RE
- .sp 1
- .SH BUGS
- .PP
- If a single letter macro name is used but never defined (in the makefile)
- \fBmaketd\fP might still use it for an abbreviation name. This should not
- effect the makefile as all the dependencies and the redefinition of the
- macro will follow the users last usage of it. This happens in DYNIX makefiles
- that use \*(lqP\*(rq to indicate that parallel compilation should be used.
- We suggest that Makefiles which use this trick put a
- .sp 1
- X P=
- .sp 1
- in the Makefile (above the all target) to keep \fImaketd\fP from using
- the macro \*(lqP\*(rq; the command line definition of P="&" will override
- the Makefile's definition.
- .PP
- Some more path compression could be done.
- .SH AUTHORS
- Stephan Bechtolsheim (a shell script), Purdue CS
- .br
- Stephen Uitti (a C version), Purdue CC
- .br
- Craig Norborg (m4 modifications), Purdue CC
- .br
- Kevin Braunsdorf (intermix options), Purdue CC
- .SH SEE ALSO
- make(1), cc(1), m4(1)
- Purdue
- chmod 0444 maketd/maketd.1l ||
- echo 'restore of maketd/maketd.1l failed'
- Wc_c="`wc -c < 'maketd/maketd.1l'`"
- test 8481 -eq "$Wc_c" ||
- echo 'maketd/maketd.1l: original size 8481, current size' "$Wc_c"
- fi
- # ============= libopt/libopt.3l ==============
- if test ! -d 'libopt'; then
- echo 'x - creating directory libopt'
- mkdir 'libopt'
- fi
- if test -f 'libopt/libopt.3l' -a X"$1" != X"-c"; then
- echo 'x - skipping libopt/libopt.3l (File already exists)'
- else
- echo 'x - extracting libopt/libopt.3l (Text)'
- sed 's/^X//' << 'Purdue' > 'libopt/libopt.3l' &&
- .\" Copyright (c) 1988 Regents of the University of California.
- .\" All rights reserved.
- .\"
- .\" Redistribution and use in source and binary forms are permitted
- .\" provided that the above copyright notice and this paragraph are
- .\" duplicated in all such forms and that any documentation,
- .\" advertising materials, and other materials related to such
- .\" distribution and use acknowledge that the software was developed
- .\" by the University of California, Berkeley. The name of the
- .\" University may not be used to endorse or promote products derived
- .\" from this software without specific prior written permission.
- .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
- .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
- .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
- .\"
- .\" @(#)getopt.3 6.8 (Berkeley) 7/9/88
- .\"
- .TH LIBOPT 3L "June 1990"
- .UC 6
- .SH NAME
- envopt, getopt, getarg, optind, optarg, optsil, rescan \- process a command line
- .SH SYNOPSIS
- #include \*(lqgetopt.h\*(rq
- .sp
- .ft B
- int getopt(argc, argv, optstring)
- .br
- int argc;
- .br
- char **argv;
- .br
- char *optstring;
- .sp
- int getarg(argc, argv)
- .br
- int argc;
- .br
- char **argv;
- .sp
- envopt(toscan)
- .br
- char *toscan;
- .sp
- extern char *optarg;
- .br
- extern int optind;
- .br
- extern int optsil;
- .sp
- int rescan()
- .ft
- .sp 1
- cc -I/usr/include/local -o tool ... -lopt
- .SH DESCRIPTION
- .I Getopt
- returns the next option letter in
- .I argv
- that matches a letter in
- .IR optstring .
- .I Optstring
- is a string of recognized option letters;
- if a letter is followed by a colon, the option is expected to have
- an argument that may or may not be separated from it by white space.
- .I Optarg
- is set to point to the start of the option argument on return from
- .IR getopt .
- .PP
- .I Getopt
- places in
- .I optind
- the
- .I argv
- index of the next argument to be processed.
- Because
- .I optind
- is external, it is normally initialized to zero automatically
- before the first call to
- .IR getopt .
- .PP
- When all options have been processed (i.e., up to the first
- non-option argument),
- .I getopt
- returns
- .BR EOF .
- The special option
- .B \-\-
- may be used to delimit the end of the options;
- .B EOF
- will be returned, and
- .B \-\-
- will be skipped.
- .PP
- After
- .IR getopt
- has returned an EOF
- .IR getarg
- may be called to extract the remaining arguments from the command line
- one at a time.
- .PP
- If another scan of the argument list is required the function
- .IR rescan ()
- may be called to reset the index into the option list.
- .PP
- If an environment variable is read as options to the program its
- value must be passed to
- .IR envopt
- before the first call the
- .IR getopt .
- .SH DIAGNOSTICS
- .I Getopt
- prints an error message on
- .I stderr
- and returns a question mark
- .RB ( ? )
- when it encounters an option letter not included in
- .IR optstring .
- Setting \fIopterr\fP to a zero will disable this error message.
- .SH EXAMPLE
- The following code fragment shows how one might process the arguments
- for a command that can take the mutually exclusive options
- .B a
- and
- .BR b ,
- and the options
- .B f
- and
- .BR o ,
- both of which require arguments:
- .PP
- .RS
- .nf
- #include <stdio.h>
- #include "getopt.h"
- X
- main(argc, argv)
- int argc;
- char **argv;
- {
- X int c;
- X extern int optind;
- X extern char *optarg;
- X extern char *getenv();
- X char *scanme;
- X \&.
- X \&.
- X \&.
- X /* option environment variable to read */
- X if (0 != (scanme = getenv("TRY")))
- X envopt(scanme);
- X \&.
- X \&.
- X \&.
- X while ((c = getopt(argc, argv, "abf:o:")) != EOF)
- X switch (c) {
- X case `a':
- X if (bflg)
- X errflg++;
- X else
- X aflg++;
- X break;
- X case `b':
- X if (aflg)
- X errflg++;
- X else
- X bproc();
- X break;
- X case `f':
- X ifile = optarg;
- X break;
- X case `o':
- X ofile = optarg;
- X break;
- X case `?':
- X default:
- X errflg++;
- X break;
- X }
- X if (errflg) {
- X fprintf(stderr, "Usage: ...");
- X exit(2);
- X }
- X while (EOF != getarg(argc, argv))) {
- X process(optarg);
- X \&.
- X \&.
- X \&.
- X }
- X \&.
- X \&.
- X \&.
- }
- .RE
- .SH HISTORY
- Written by Henry Spencer, working from a Bell Labs manual page.
- Modified by Keith Bostic to behave more like the System V version.
- Modified by Kevin Braunsdorf to read environment variables.
- .SH BUGS
- ``-'' may be specified as an option letter, however it should never have
- an argument associated with it. This allows getopt to be used with
- programs that think that ``-'' means standard input.
- .PP
- Option arguments are allowed to begin with ``\-'';
- this is reasonable but reduces the amount of error checking possible.
- .PP
- .I Getopt
- is quite flexible but the obvious price must be paid: there is much
- it could do that it doesn't, like
- checking mutually exclusive options, checking type of
- option arguments, etc.
- Purdue
- chmod 0444 libopt/libopt.3l ||
- echo 'restore of libopt/libopt.3l failed'
- Wc_c="`wc -c < 'libopt/libopt.3l'`"
- test 4616 -eq "$Wc_c" ||
- echo 'libopt/libopt.3l: original size 4616, current size' "$Wc_c"
- fi
- # ============= libsrtunq/libsrtunq.3l ==============
- if test ! -d 'libsrtunq'; then
- echo 'x - creating directory libsrtunq'
- mkdir 'libsrtunq'
- fi
- if test -f 'libsrtunq/libsrtunq.3l' -a X"$1" != X"-c"; then
- echo 'x - skipping libsrtunq/libsrtunq.3l (File already exists)'
- else
- echo 'x - extracting libsrtunq/libsrtunq.3l (Text)'
- sed 's/^X//' << 'Purdue' > 'libsrtunq/libsrtunq.3l' &&
- .\" # my routine titler -- accepts the lines of the title as args
- .de TM
- .in .5i
- .B \\$1
- .br
- .B \\$2
- .br
- .B \\$3
- .br
- .B \\$4
- .br
- .B \\$5
- .br
- .B \\$6
- .br
- .B \\$7
- .br
- .B \\$8
- .br
- .B \\$9
- .br
- .ft R
- .in +.5i
- ..
- '
- '
- '
- .TH SRTUNQ 3L PUCC
- .SH NAME
- srtdel, srtinit, srtin, srtmem, srtgti, srtgets, srtapply, srtfree, srtdtree \- in memory
- string sorting
- .SH SYNOPSIS
- .B #include <stdio.h>
- .br
- .B #include \*(lqsrtunq.h\*(rq
- .sp
- cc \-I/usr/include/local file.c
- .B \-lsrtunq
- .SH DESCRIPTION
- .I Libsrtunq.a
- is used to extract unique items from a possibly long list,
- where items are likely to be replicated numerously.
- The list of unique items must be small enough to
- fit in memory, but the number of repetitions is possibly high.
- .PP
- The caller has control over the database through the use of a
- \fBSRTTABLE\fP variable. The subroutines provide for data entry and
- retrieval, memory allocation and deallocation.
- .SH ROUTINES
- .TM "typedef struct ... SRTTABLE;"
- Users will define one variable of this type to hold the root of
- each sorted list they wish to keep.
- Most routines in this library require the address of such
- a variable as their first argument.
- X
- .TM "typedef struct ... SRTENTRY;"
- Strings are kept in a structure of this type internally.
- The user should not depend on the internal details of this type.
- X
- .TM "void" "srtinit(tbl)" "SRTTABLE *tbl;"
- This subroutine must be called to initialize the database tag \fItbl\fP
- before any data are entered or retrieved from that tree.
- It assumes that the tag has not been used
- to store a tree, and therefore does not attempt to free any such data.
- X
- .TM "char *" "srtin(tbl, string, compare)" "SRTTABLE *tbl;" "char *string;" "int (*compare)();"
- The existing data tree is searched for the string,
- if it is found then a pointer to that string is returned.
- Otherwise, space is allocated for the string and pointer structure via
- \fImalloc\fP(3).
- The string is copied to this new space which is linked into the tree
- and a pointer to the new string is returned.
- If space cannot be obtained, the operation is aborted and NULL is returned
- (the data structure remains consistent, but the string is not added).
- The strings are compared and sorted with the subroutine pointed to by
- \fIcompare\fP. This subroutine takes two string pointers as arguments.
- It returns zero if the strings are the same,
- less than zero if the first string should precede the second, and
- greater than zero if the second string should precede the first.
- Use \fIstrcmp\fP(3) if simple lexicographical ordering is desired.
- It is confusing at best if different \fIcompare\fP functions are used
- when inserting strings into a given tree.
- X
- .TM "char *" "srtmem(tbl, string, compare)" "SRTTABLE *tbl;" "char *string;" "int (*compare)();"
- Return the database entry for \fIstring\fP if it is already a member of
- the table, else NULL.
- X
- .TM "int" "srtdel(tbl, string, compare)" "SRTTABLE *tbl;" "char *string;" "int (*compare)();"
- The existing data tree is searched for the string,
- if it is found then it is deleted and a nonzero value is returned.
- Otherwise, 0 is returned.
- X
- .TM "void" "srtgti(tbl);" "SRTTABLE *tbl;"
- This subroutine initializes the database tag pointed to by \fItbl\fP
- so that a tree traversal can be made via \fIsrtgets\fP.
- X
- .TM "char *" "srtgets(tbl);" "SRTTABLE *tbl;"
- This subroutine extracts the next string from the data structure.
- The strings are returned in the order specified by the \fIcompare\fP
- function when they were inserted with \fIsrtin\fP.
- When the list is exhausted, NULL is returned.
- X
- .TM "int" "srtapply(tbl, func)" "SRTTABLE *tbl;" "int (*func)();"
- This subroutine applies the \fIfunc\fP to each string in the tree (order
- determined by \fIcompare\fP when they were inserted) until the func returns
- non-zero, or there are no more strings. If the \fIfunc\fP returned
- non-zero then that value is returned, otherwise 0 is returned.
- X
- .TM "void" "srtfree(tbl)" "SRTTABLE *tbl;"
- This subroutine deletes a database, and re-initializes the
- database tag.
- It assumes that the database tag was initialized at one time via \fIsrtinit\fP
- (other routines will probably also have been called).
- The space formally occupied by string data and pointer structures is
- deallocated via \fIfree\fP(3).
- X
- .TM "void" "srtdtree(tbl, ent)" "SRTTABLE *tbl;" "SRTENTRY *ent;"
- This subroutine recursively deletes a database subtree.
- The space formally occupied by the string data and pointer structures is
- deallocated via \fIfree\fP(3).
- This routine is most likely only of use internally.
- .SH EXAMPLE
- .nf
- #include <stdio.h>
- main()
- {
- X extern int strcmp();
- X SRTTABLE tree;
- X char buf[80], *p;
- X int i;
- X
- X /* init the tree */
- X srtinit(&tree);
- X
- X /* add some strings */
- X while (NULL != fgets(buf, 80, stdin)) /* want the \en terminator */
- X if (NULL == (p = srtin(&tree, buf, strcmp)))
- X printf("out of memory!\en");
- X
- X /* init tree for srtgets */
- X srtgti(&tree);
- X
- X /* print out the strings with srtapply and printf -- can't have
- X * a legal printf % escape in the strings! */
- X (void) srtapply(&tree, printf);
- X
- X /* use srtgets to print the strings out this time -- keep count */
- X for (i = 0; NULL != (p = srtgets(&tree)); ++i)
- X printf("string %2d is: %s\en", i, p);
- X printf("there were %d strings\en", i);
- X
- X /* free the database */
- X srtfree(&tree);
- }
- .fi
- .SH DIAGNOSTICS
- There are no messages printed by these routines.
- Catchable errors are returned as NULL.
- Compiled in errors such as the use of strings that
- are not null terminated tend to result in core files.
- .SH FILES
- /usr/local/lib/libsrtunq.a
- .br
- /usr/include/local/srtunq.h
- .SH SEE ALSO
- malloc(3), free(3), qsort(3), strcmp(3)
- .SH AUTHOR
- Stephen Uitti, PUCC
- .SH BUGS
- The structure names and typedefs seem confused. The typedefs make more sense.
- Purdue
- chmod 0444 libsrtunq/libsrtunq.3l ||
- echo 'restore of libsrtunq/libsrtunq.3l failed'
- Wc_c="`wc -c < 'libsrtunq/libsrtunq.3l'`"
- test 5705 -eq "$Wc_c" ||
- echo 'libsrtunq/libsrtunq.3l: original size 5705, current size' "$Wc_c"
- fi
- # ============= maketd/abrv.c ==============
- if test -f 'maketd/abrv.c' -a X"$1" != X"-c"; then
- echo 'x - skipping maketd/abrv.c (File already exists)'
- else
- echo 'x - extracting maketd/abrv.c (Text)'
- sed 's/^X//' << 'Purdue' > 'maketd/abrv.c' &&
- /*
- X * abbreviation related routines
- X * Written & hacked by Stephen Uitti, PUCC staff
- X * 1985 maketd is copyright (C) Purdue University, 1985
- X *
- X * Permission is hereby given for its free reproduction and modification for
- X * non-commercial purposes, provided that this notice and all embedded
- X * copyright notices be retained. Commercial organizations may give away
- X * copies as part of their systems provided that they do so without charge,
- X * and that they acknowledge the source of the software.
- X */
- X
- #include "machine.h"
- X
- #ifdef pdp11
- #include <sys/types.h>
- #endif
- #include <stdio.h>
- #include <ctype.h>
- X
- extern char *strrchr();
- X
- #include "srtunq.h"
- #include "abrv.h"
- #include "main.h"
- #include "maketd.h"
- #include "errors.h"
- X
- #define SPACE '\040' /* ascii for space */
- X
- struct srtent abrv; /* include file abrevs */
- char *abrvtbl[MXABR]; /* translation table strings */
- int abrvlen[MXABR]; /* string lengths (for speed) */
- X
- /*
- X * lngsrt - string length more important than lexicographical compare.
- X * return > 0 if b is longer than a.
- X * return < 0 if b is shorter than a.
- X * if a & b are * the same length, return strcmp(a, b), which means that
- X * 0 is returned if the strings are THE SAME,
- X * if b > a: return > 0 if b < a: return < 0
- X */
- int
- lngsrt(a, b)
- char *a, *b;
- {
- X register int i;
- X
- X if (0 != (i = strlen(b) - strlen(a)))
- X return i;
- X return strcmp(a, b);
- }
- X
- /*
- X * hincl - include header optimizer:
- X * Compress multiple leading /'s to just one. Remove leading "./".
- X * Doesn't change date, just returns pointer into beginning of path.
- X */
- char *
- hincl(p)
- register char *p;
- {
- X if ('/' == *p) { /* compress multiple leading /'s */
- X while ('/' == p[1]) /* to just one */
- X ++p;
- X }
- X if (0 == strncmp("./", p, 2)) {
- X p += 2; /* leading "./" can confuse make */
- X while ('/' == *p) /* don't change ".//a.h" to "/a.h" */
- X ++p;
- X }
- X return p;
- }
- X
- /* makeabrv
- X * add an abreviation to the table
- X */
- void
- makeabrv(pos, p)
- int pos;
- char *p;
- {
- X register int len;
- X
- X if (NULL != abrvtbl[pos]) {
- X fprintf(stderr, "%s: macro letter '%c' redefined\n", progname, 'A' + pos);
- X return;
- X }
- X abrvtbl[pos] = p;
- X if (3 > (len = strlen(p))) { /* don't use, but hold letter */
- X len = 0;
- X }
- X abrvlen[pos] = len;
- X if (FALSE != verbose) {
- X fprintf(stderr, "%s: %c='%s'\n", progname, pos + 'A', p);
- X }
- }
- X
- /*
- X * srchincl - search line for make defines of A-Z Put entries into abrvtbl.
- X */
- void
- srchincl(p)
- register char *p;
- {
- X register char letter, *q, *r;
- X register unsigned i;
- X extern char *malloc();
- X
- X if (FALSE == shortincl || '\000' == *p) {
- X return;
- X }
- X
- X while (isspace(*p)) /* ignore white space */
- X ++p;
- X letter = *p++;
- X if (! isupper(letter)) {
- X return;
- X }
- X
- X while (isspace(*p))
- X ++p;
- X if ('=' != *p++) {
- X return;
- X }
- X
- X while (isspace(*p))
- X ++p;
- X i = strlen(p);
- X
- X if (NULL == (q = r = malloc(i+1))) {
- X OutOfMemory();
- X }
- X
- X while ('\000' != *p && '#' != *p && ! isspace(*p))
- X *q++ = *p++;
- X *q = '\000';
- X
- X makeabrv(letter-'A', r);
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: use macro %c as %s\n", progname, letter, r);
- }
- X
- /*
- X * abrvsetup - set up abrev table, spit out the abrevs.
- X * Use any A-Z definitions found in Makefile, no duplicates.
- X * look at each sting we have noticed as a prefix
- X * (make sure is non-NULL, not too small)
- X * macro them
- X * output table
- X */
- void
- abrvsetup()
- {
- X register int i; /* scan tables */
- X register char *p; /* surrent abrev. canidate */
- X register char *q; /* temp string */
- X register int slot; /* slot search point */
- X
- X srtgti(&abrv);
- X while (NULL != (p = srtgets(&abrv))) {
- X if (FALSE != verbose)
- X fprintf(stderr, "%s: examine %s, ", progname, p);
- X slot = -1;
- X for (i = 0; i < MXABR; ++i) {
- X q = abrvtbl[i];
- X if (NULL == q) {
- X if (slot == -1)
- X slot = i;
- X continue;
- X }
- X if (0 == strcmp(p, q))
- X break;
- X }
- X
- X /* already in table or no more room in table
- X */
- X if (MXABR != i || slot == -1) {
- X if (FALSE != verbose)
- X fprintf(stderr, "rejected\n");
- X continue;
- X }
- X
- X /* slot is a known free slot,
- X * but we'd rather be mnemonic
- X */
- X q = strrchr(p, '/');
- X if ((char *)0 != q && isalpha(q[1])) {
- X i = q[1] - (islower(q[1]) ? 'a' : 'A');
- X if (NULL == abrvtbl[i])
- X slot = i;
- X }
- X if (FALSE != verbose)
- X fprintf(stderr, "accepted as %c\n", slot+'A');
- X makeabrv(slot, p);
- X fprintf(makefp, "%c=%s\n", slot+'A', p);
- X }
- }
- X
- /*
- X * findabr - find an abbreviation in abrvtbl for string p (if any).
- X * if multiple abbreations work, use longest. (ie: /usr/include &
- X * /usr/include/sys; use /usr/include/sys) if found, return index else: MXABR
- X */
- int
- findabr(p)
- register char *p; /* string pointer */
- {
- X register int i; /* for index */
- X register int j; /* found index */
- X
- X for (i = 0, j = MXABR; i < MXABR; ++i) {
- X if (0 == abrvlen[i])
- X continue;
- X if (0 == strncmp(abrvtbl[i], p, abrvlen[i]))
- X if (MXABR == j || abrvlen[i] > abrvlen[j])
- X j = i;
- X }
- X return j;
- }
- Purdue
- chmod 0444 maketd/abrv.c ||
- echo 'restore of maketd/abrv.c failed'
- Wc_c="`wc -c < 'maketd/abrv.c'`"
- test 4905 -eq "$Wc_c" ||
- echo 'maketd/abrv.c: original size 4905, current size' "$Wc_c"
- fi
- # ============= libopt/envopt.c ==============
- if test -f 'libopt/envopt.c' -a X"$1" != X"-c"; then
- echo 'x - skipping libopt/envopt.c (File already exists)'
- else
- echo 'x - extracting libopt/envopt.c (Text)'
- sed 's/^X//' << 'Purdue' > 'libopt/envopt.c' &&
- /*
- X * take options from an envirionment variable
- X */
- #include <stdio.h>
- #include "getopt.h"
- X
- extern char **_eargv;
- extern int _eargc;
- X
- /* breakargs - break a string into a string vector for execv.
- X * Note, when done with the vector, mearly "free" the vector.
- X * Written by Stephen Uitti, PUCC, Nov '85 for the new version
- X * of "popen" - "nshpopen", that doesn't use a shell.
- X * (used here for the as filters, a newer option).
- X *
- X * breakargs is copyright (C) Purdue University, 1985
- X *
- X * put in a fix for cmds lines with "string string" in them
- X * Mon Aug 25 13:34:27 EST 1986 (ksb)
- X *
- X * Permission is hereby given for its free reproduction and
- X * modification for non-commercial purposes, provided that this
- X * notice and all embedded copyright notices be retained.
- X * Commercial organisations may give away copies as part of their
- X * systems provided that they do so without charge, and that they
- X * acknowledge the source of the software.
- X */
- #ifdef BSD2_9
- #include <sys/types.h>
- #endif
- #include <stdio.h> /* for nothing, really */
- #define SPC '\040' /* ascii space */
- X
- char *
- mynext(pch)
- register char *pch;
- {
- X register int fQuote;
- X
- X for (fQuote = 0; (*pch != '\000' && *pch != SPC && *pch != '\t')||fQuote; ++pch) {
- X if ('\\' == *pch) {
- X continue;
- X }
- X switch (fQuote) {
- X default:
- X case 0:
- X if ('"' == *pch) {
- X fQuote = 1;
- X } else if ('\'' == *pch) {
- X fQuote = 2;
- X }
- X break;
- X case 1:
- X if ('"' == *pch)
- X fQuote = 0;
- X break;
- X case 2:
- X if ('\'' == *pch)
- X fQuote = 0;
- X break;
- X }
- X }
- X return pch;
- }
- X
- /*
- X * given an envirionment variable insert it in the option list (exploded)
- X */
- int
- envopt(cmd)
- char *cmd;
- {
- X register char *p; /* tmp */
- X register char **v; /* vector of commands returned */
- X register unsigned sum; /* bytes for malloc */
- X register int i; /* number of args */
- X register char *s; /* save old position */
- X register char hold; /* hold a character for a second*/
- X extern char *malloc(), *strcpy();
- X
- X p = cmd;
- X while (*p == SPC || *p == '\t')
- X p++;
- X cmd = p; /* no leading spaces */
- X sum = sizeof(char *);
- X i = 1;
- X while (*p != '\0') { /* space for argv[]; */
- X ++i;
- X s = p;
- X p = mynext(p);
- X sum += sizeof(char *) + 1 + (unsigned)(p - s);
- X while (*p == SPC || *p == '\t')
- X p++;
- X }
- X ++i;
- X /* vector starts at v, copy of string follows NULL pointer */
- X v = (char **)malloc(sum+sizeof(char *));
- X if (v == NULL)
- X return 0;
- X p = (char *)v + i * sizeof(char *); /* after NULL pointer */
- X i = 0; /* word count, vector index */
- X v[i++] = "";
- X while (*cmd != '\0') {
- X v[i++] = p;
- X s = cmd;
- X cmd = mynext(cmd);
- X hold = *cmd;
- X *cmd = '\000';
- X strcpy(p, s);
- X p += strlen(p);
- X ++p;
- X if ('\000' != hold)
- X *cmd++ = hold;
- X while (*cmd == SPC || *cmd == '\t')
- X ++cmd;
- X }
- X v[i] = (char *)NULL;
- X _eargv = v;
- X _eargc = i;
- X return i;
- }
- Purdue
- chmod 0444 libopt/envopt.c ||
- echo 'restore of libopt/envopt.c failed'
- Wc_c="`wc -c < 'libopt/envopt.c'`"
- test 2814 -eq "$Wc_c" ||
- echo 'libopt/envopt.c: original size 2814, current size' "$Wc_c"
- fi
- true || echo 'restore of maketd/main.c failed'
- echo End of part 1, continue with part 2
- exit 0
-
- exit 0 # Just in case...
-