home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / pucc-lib / part01 next >
Text File  |  1991-03-19  |  57KB  |  2,192 lines

  1. Subject:  v24i055:  Library for Purdue University Computing Center tools, Part01/02
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 62517344 5cc85733 e878b79d ecdcfd69
  5.  
  6. Submitted-by: Kevin Braunsdorf <ksb@cc.purdue.edu>
  7. Posting-number: Volume 24, Issue 55
  8. Archive-name: pucc-lib/part01
  9.  
  10. This two part archive contains the libraries that most of the PUCC
  11. (Purdue University Computing Center) tools require to compile.  You'll
  12. need to build these to compile any of the nifty stuff that follows.
  13. Included are:
  14.     libopt(3l)    - process a command line
  15.     maketd(1l)    - edit a makefile to update transitive dependencies
  16.     srtunq(3l)    - in memory string sorting
  17. -- ksb
  18.  
  19.  
  20. #!/bin/sh
  21. # This is pucc-1a, a shell archive (produced by shar 3.49)
  22. # To extract the files from this archive, save it to a file, remove
  23. # everything above the "!/bin/sh" line above, and type "sh file_name".
  24. #
  25. # made 11/29/1990 15:57 UTC by ksb@cc.purdue.edu (Kevin Braunsdorf)
  26. # Source directory /ksb/c.s.u-2
  27. #
  28. # existing files will NOT be overwritten unless -c is specified
  29. #
  30. # This shar contains:
  31. # length  mode       name
  32. # ------ ---------- ------------------------------------------
  33. #   1321 -rw-r--r-- INSTALL.01
  34. #  21424 -r--r--r-- maketd/maketd.c
  35. #   8481 -r--r--r-- maketd/maketd.1l
  36. #   4616 -r--r--r-- libopt/libopt.3l
  37. #   5705 -r--r--r-- libsrtunq/libsrtunq.3l
  38. #   4905 -r--r--r-- maketd/abrv.c
  39. #   2814 -r--r--r-- libopt/envopt.c
  40. #   4235 -r--r--r-- maketd/main.c
  41. #   3826 -r--r--r-- maketd/M4.patch
  42. #   1360 -rw-r--r-- libopt/Makefile
  43. #    619 -rw-r--r-- libopt/README
  44. #   1999 -r--r--r-- libopt/getopt.c
  45. #   2793 -rw-r--r-- libsrtunq/Makefile
  46. #   2530 -r--r--r-- libsrtunq/srtdel.c
  47. #   2731 -rw-r--r-- maketd/Makefile
  48. #   2359 -r--r--r-- maketd/errors.c
  49. #   1514 -r--r--r-- libsrtunq/srtapply.c
  50. #   1452 -r--r--r-- libsrtunq/srtgets.c
  51. #   1723 -r--r--r-- libsrtunq/srtin.c
  52. #   1226 -r--r--r-- libsrtunq/srtdtree.c
  53. #   1240 -r--r--r-- libsrtunq/srtmem.c
  54. #   1278 -rw-r--r-- maketd/machine.h
  55. #   1148 -r--r--r-- libopt/getopt.h
  56. #   1067 -r--r--r-- libsrtunq/srtfree.c
  57. #   1067 -r--r--r-- libsrtunq/srtgti.c
  58. #   1011 -r--r--r-- libsrtunq/srtinit.c
  59. #   1144 -r--r--r-- maketd/maketd.h
  60. #    819 -r--r--r-- libsrtunq/srtunq.h
  61. #    621 -r--r--r-- maketd/abrv.h
  62. #    519 -r--r--r-- libopt/getarg.c
  63. #    490 -r--r--r-- libsrtunq/README
  64. #    471 -r--r--r-- maketd/GCC.awk
  65. #    310 -r--r--r-- maketd/errors.h
  66. #    256 -r--r--r-- libopt/rescan.c
  67. #    245 -r--r--r-- maketd/README
  68. #    216 -r--r--r-- maketd/main.h
  69. #
  70. # ============= INSTALL.01 ==============
  71. if test -f 'INSTALL.01' -a X"$1" != X"-c"; then
  72.     echo 'x - skipping INSTALL.01 (File already exists)'
  73. else
  74. echo 'x - extracting INSTALL.01 (Text)'
  75. sed 's/^X//' << 'Purdue' > 'INSTALL.01' &&
  76. Contains:
  77. X    libopt(3l)    - process a command line
  78. X    maketd(1l)    - edit a makefile to update transitive dependencies
  79. X    srtunq(3l)    - in memory string sorting
  80. X
  81. X
  82. Notes on depends:
  83. X    - libopt.a and libsrtunq.a need not be installed, but it
  84. X      would make life easier if you want other PUCC tools.
  85. X
  86. X    - maketd needs libopt.a and libsrtunq.a to compile
  87. X
  88. X
  89. To install these tools:
  90. X
  91. 0\ read the manual pages, see if you want any of them
  92. X
  93. 1\ vi libopt/Makefile and set DEFS if we do not have strchr/strrchr
  94. X    vi libopt/Makefile
  95. X
  96. 2\ build libopt and libsrtunq, ranlib them if you have to
  97. X    (cd libopt && make)
  98. X    (cd libsrtunq && make)
  99. X
  100. X    ranlib libopt/libopt.a libsrtunq/libsrtunq.a
  101. X
  102. 3\ decide where to install all this stuff, change the destinations in
  103. X   the Makefiles {BIN,LIB,ETC,HEADER}
  104. X    vi */Makefile
  105. X    
  106. 4\ install libopt and libsrtunq if you decided to
  107. X    su
  108. X    (cd libopt && make install)
  109. X    (cd libsrtunq && make install)
  110. X    exit
  111. X
  112. 4\ build maketd
  113. X    (cd maketd && make)
  114. X
  115. 5\ install maketd
  116. X    su root
  117. X    (cd maketd && make install)
  118. X    exit
  119. X
  120. 6\ clean up the dirs
  121. X    (cd libopt && make clean)
  122. X    (cd libsrtunq && make clean)
  123. X    (cd maketd && make clean)
  124. X
  125. 7\ if you have mkcat install any manual pages you want
  126. X    su root
  127. X    mkcat -v maketd/maketd.1l libopt/libopt.3l libsrtunq/srtunq.3l
  128. X    exit
  129. X
  130. kayessbee
  131. --
  132. Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb
  133. Purdue
  134. chmod 0644 INSTALL.01 ||
  135. echo 'restore of INSTALL.01 failed'
  136. Wc_c="`wc -c < 'INSTALL.01'`"
  137. test 1321 -eq "$Wc_c" ||
  138.     echo 'INSTALL.01: original size 1321, current size' "$Wc_c"
  139. fi
  140. # ============= maketd/maketd.c ==============
  141. if test ! -d 'maketd'; then
  142.     echo 'x - creating directory maketd'
  143.     mkdir 'maketd'
  144. fi
  145. if test -f 'maketd/maketd.c' -a X"$1" != X"-c"; then
  146.     echo 'x - skipping maketd/maketd.c (File already exists)'
  147. else
  148. echo 'x - extracting maketd/maketd.c (Text)'
  149. sed 's/^X//' << 'Purdue' > 'maketd/maketd.c' &&
  150. /*
  151. X * the real brains are in this file
  152. X */
  153. #include "machine.h"
  154. X
  155. #include <stdio.h>
  156. #include <sys/types.h>
  157. #include <sys/file.h>
  158. #include <sys/stat.h>
  159. #include <ctype.h>
  160. #if defined(SYSV)
  161. #include <string.h>
  162. #include "bsd.h"
  163. #else
  164. #include <strings.h>
  165. #endif
  166. X
  167. extern FILE *popen();
  168. extern int errno;
  169. extern char *sys_errlist[];
  170. #define strerror(Me) (sys_errlist[Me])
  171. X
  172. #include "main.h"
  173. #include "maketd.h"
  174. #include "srtunq.h"
  175. #include "abrv.h"
  176. #include "errors.h"
  177. X
  178. #if !defined(F_OK)
  179. #define F_OK    0
  180. #endif
  181. X
  182. /*
  183. X * if your cpp doesn't grok -M use something like this...
  184. X *    "/lib/cpp -E %I %F |sed -n 's@^# *[0-9]* *"\\(.*\\)"@%f: \\1@p'"
  185. X * to format the lines into `file.o: file.d'
  186. X * Otherwise use:
  187. X *    "/lib/cpp -M %I %F",
  188. X * the line for gcc's cpp is not so short, but it can be done.
  189. X * (See GCC.awk for a description, and some clues.)
  190. X */
  191. X
  192. char *preprocessors[] = {
  193. #if defined(CPP)
  194. X    CPP,
  195. #else
  196. #if defined(CPP_M)
  197. X    "/lib/cpp -M %I %F",
  198. #else
  199. X    /* once for C, once for expand, once for sed */
  200. X    "/lib/cpp -E %I %F |sed -n 's@^# *[0-9]* *\"\\\\(.*\\\\)\"@%f: \\\\1@p'",
  201. #endif
  202. #endif
  203. X
  204. #if defined(M4)
  205. X    M4
  206. #else
  207. X    "/usr/bin/m4 -M %F"
  208. #endif
  209. };
  210. X
  211. char
  212. X    *pchBackup;    /* the backup file name                */
  213. X
  214. FILE    *makefp;    /* file pointer to the dest makefile        */
  215. int
  216. X    backedup = FALSE; /* is the backup file is present        */
  217. X
  218. static struct srtent
  219. X    incld;
  220. static DependInfo
  221. X    FileInfo = {    /* our template for all files            */
  222. X        0, 0,
  223. X        NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
  224. X        (DependInfo *)0
  225. X    };
  226. static FILE
  227. X    *fpBackup,    /* file pointer to the backup file        */
  228. X    *fpPipe;    /* pipe file pointer for preproc        */
  229. static char
  230. X    sbInc[] =
  231. #if defined(INCLD)
  232. X        INCLD,
  233. #else
  234. X        "/usr/include",
  235. #endif
  236. X    deplin[] =
  237. X        "# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT\n",
  238. X    searchdep[] =
  239. X        "# DO NOT DELETE THIS LINE",
  240. X    trailer[] =
  241. X        "\n# *** Do not add anything here - It will go away. ***\n";
  242. X
  243. /* SetPP
  244. X * This routine changes the preprocessor to be used on the next filename.
  245. X * It has one argument (i) that is the number of the preprocessor to use
  246. X *    0 == /lib/cpp
  247. X *    1 == /usr/bin/m4
  248. X */
  249. int
  250. SetPP(i)
  251. int i;
  252. {
  253. X    FileInfo.preprocessor = preprocessors[i];
  254. }
  255. X
  256. /* user filter
  257. X * This routine allows the user to scan anything he can code a program
  258. X * (script?) to produce `file.z: dep.x' lines on std for, like
  259. X *
  260. X * /lib/cpp -E %I %F | sed -n 's/^# *[0-9]* *"\(.*\)"/%f: \1/p'
  261. X */
  262. int
  263. UserFilter(pcFilter)
  264. char *pcFilter;
  265. {
  266. X    if ((char *)0 == pcFilter || '\000' != pcFilter[0])
  267. X        FileInfo.preprocessor = pcFilter;
  268. X    else
  269. X        FileInfo.preprocessor = (char *)0;
  270. }
  271. X
  272. X
  273. /* SetSuffix
  274. X * This routine changes the suffix to add to the next file that is processed.
  275. X * If binary is set, it goes into binary mode. The only way to unset binary
  276. X * mode is to set a new suffix.
  277. X */
  278. int
  279. SetSuffix(option, suffix)
  280. int option;
  281. char *suffix;
  282. {
  283. X    if ('b' == option) {
  284. X        FileInfo.binarydep = 1;
  285. X    } else {
  286. X        FileInfo.suffix    = STRSAVE(suffix);
  287. X        FileInfo.binarydep = 0;
  288. X    }
  289. }
  290. X
  291. /* SetLocalO
  292. X * Hey, what more can I say, this sets the local-o and the non-local o
  293. X * options in the file structure.
  294. X */
  295. int
  296. SetLocalO(i)
  297. int i;
  298. {
  299. X    FileInfo.localo = i;
  300. }
  301. X
  302. /* SetCPPFlags
  303. X * This function sets the CPP flags. It is given two arguments, the
  304. X * option (CDIU), and the argument given. If the option is C, it
  305. X * clears the previous CPP flags. Otherwise, it just catentiates a
  306. X * string of options.
  307. X */
  308. int
  309. SetCPPFlags(option, argument)
  310. int option;
  311. char *argument;
  312. {
  313. X    register char *pch = NULL;
  314. X    register unsigned len;
  315. X    static char sbOption[4] = " -?";
  316. X    extern char *malloc(), *realloc();
  317. X
  318. X    if ('C' == option) {
  319. X        if (NULL != FileInfo.cppflags) {
  320. X            free(FileInfo.cppflags);
  321. X            FileInfo.cppflags = NULL;
  322. X        }
  323. X        return ;
  324. X    } 
  325. X    pch = FileInfo.cppflags;
  326. X    len = strlen(argument)+4;
  327. X    if (NULL == pch) {
  328. X        FileInfo.cppflags = malloc(len);
  329. X        FileInfo.cppflags[0] = '\000';
  330. X    } else {
  331. X        len += strlen(pch);
  332. X        FileInfo.cppflags = realloc(FileInfo.cppflags, len);
  333. X    }
  334. X    sbOption[2] = option;
  335. X    strcat(FileInfo.cppflags, sbOption);
  336. X    strcat(FileInfo.cppflags, argument);
  337. X
  338. X    /* insert -I files includes into abbreviation list
  339. X     */
  340. X    if ('I' == option) {
  341. X        /* if we end in '/' take it off */
  342. X        pch = strrchr(argument, '/');
  343. X        if ((char *)0 != pch && '\000' == pch[1]) 
  344. X            pch[1] = '\000';
  345. X        if (NULL == srtin(&abrv, hincl(argument), lngsrt)) {
  346. X            OutOfMemory();
  347. X        }
  348. X        if (FALSE != verbose)
  349. X            fprintf(stderr, "%s: inserted abbr %s\n", progname, argument);
  350. X    }
  351. }
  352. X
  353. /* SetObjPath
  354. X *    tell processing part about non-local dot-o's
  355. X */
  356. int
  357. SetObjPath(destdir)
  358. char *destdir;
  359. {
  360. X    FileInfo.destdir = '.' == FileInfo.destdir[0] && '\000' == FileInfo.destdir ? NULL : STRSAVE(destdir);
  361. }
  362. X
  363. /* SetTargetName
  364. X * we don't ned to string save it because only one file can use it, and
  365. X * it will string save it.
  366. X */
  367. int
  368. SetTargetName(basename)
  369. char *basename;
  370. {
  371. X    FileInfo.basename = basename;
  372. }
  373. X
  374. int
  375. FileArgs(filename)
  376. char *filename;
  377. {
  378. X    register DependInfo *pDI = &FileInfo;
  379. X
  380. X    while (NULL != pDI->next)
  381. X        pDI = pDI->next;
  382. X    pDI->next = (DependInfo *)malloc((unsigned)sizeof(DependInfo));
  383. X    pDI = pDI->next;
  384. X    pDI->localo = FileInfo.localo;
  385. X    pDI->binarydep = FileInfo.binarydep;
  386. X    pDI->filename = STRSAVE(filename);
  387. X    pDI->inlib = inlib;
  388. X    
  389. X    if (FileInfo.preprocessor)
  390. X        pDI->preprocessor = FileInfo.preprocessor;
  391. X    else
  392. X        pDI->preprocessor = preprocessors[0];
  393. X
  394. X    pDI->explicit = explicit;    /* from main.c parser    */
  395. X
  396. X    pDI->cppflags = pDI->destdir = pDI->suffix = pDI->basename = (char *)0;
  397. X    if (NULL != FileInfo.cppflags)
  398. X        pDI->cppflags = STRSAVE(FileInfo.cppflags);
  399. X    if (NULL != FileInfo.destdir)
  400. X        pDI->destdir = STRSAVE(FileInfo.destdir);
  401. X    if (NULL != FileInfo.suffix)
  402. X        pDI->suffix = STRSAVE(FileInfo.suffix);
  403. X    if (NULL != FileInfo.basename)
  404. X        pDI->basename = STRSAVE(FileInfo.basename);
  405. X    pDI->next = NULL;
  406. X    FileInfo.basename = NULL;
  407. }
  408. X
  409. /* BackUp
  410. X *    Back up the makefile into the backup makefile.
  411. X */
  412. void
  413. BackUp()
  414. {
  415. X    register unsigned len;
  416. X    if (NULL == exten) {
  417. X        exten = STRSAVE(".bak");
  418. X    }
  419. X    
  420. X    len = strlen(makename)+strlen(exten)+2;
  421. X    pchBackup = malloc(len);
  422. X    strcpy(pchBackup, makename);
  423. X    if ('.' != *exten) {
  424. X        strcat(pchBackup, ".");
  425. X    }
  426. X    strcat(pchBackup, exten);
  427. X
  428. X    /* Remove the old backup file */
  429. X    if (0 == access(pchBackup, F_OK) && 0 != unlink(pchBackup)) {
  430. X        fprintf(stderr, "%s: unlink: %s: %s\n", progname, pchBackup, strerror(errno));
  431. X        exit(3);
  432. X    }
  433. X
  434. X    /* Move current makefile to backup file */
  435. X    if (0 != link(makename, pchBackup)) {
  436. X        fprintf(stderr, "%s: link: %s to %s: %s\n", progname, makename, pchBackup, strerror(errno));
  437. X        exit(4);
  438. X    }
  439. X
  440. X    backedup = TRUE;
  441. X    if (0 != unlink(makename)) {
  442. X        fprintf(stderr, "%s: unlink: %s: %s\n", progname, makename, strerror(errno));
  443. X        RestoreFiles();
  444. X    }
  445. }
  446. X
  447. /* DestName
  448. X * Given the info about the file, figure out what the destination name
  449. X * should be on the dependancy line.
  450. X */
  451. char *
  452. DestName(file)
  453. DependInfo *file;
  454. {
  455. X    static char buf[BUFSIZE];
  456. X    register char *pch = NULL;
  457. X
  458. X    /* find a prefix:
  459. X     * the -o (destdir) flag has precedence over the -n or -l flags;
  460. X     * then the non-local o option;
  461. X     * else we don't want one
  462. X     */
  463. X    if (NULL != file->destdir) {
  464. X        strcpy(buf, file->destdir);
  465. X        pch = strrchr(buf, '\000');
  466. X        if ('/' != *--pch) {
  467. X            *++pch = '/';
  468. X            *++pch = '\000';
  469. X        }
  470. X    } else if (FALSE != file->localo) {
  471. X        strcpy(buf, file->filename);
  472. X        if (NULL != (pch = strrchr(buf, '/'))) {
  473. X            pch[1] = '\000';
  474. X        }
  475. X    } else {
  476. X        buf[0] = '\000';
  477. X    }
  478. X
  479. X    /* find a basename
  480. X     * when they supplied the basename, trust them
  481. X     * else strip off any leading pathname to the file and save it in buf
  482. X     *    (but get rid of the suffix too)
  483. X     * thus buf contains only the basename
  484. X     */
  485. X    if (NULL != file->basename) {
  486. X        strcat(buf, file->basename);
  487. X    } else {
  488. X        if (NULL == (pch = strrchr(file->filename, '/'))) {
  489. X            pch = file->filename;
  490. X        } else {
  491. X            ++pch;
  492. X        }
  493. X        strcat(buf, pch);
  494. X        if (NULL != (pch = strrchr(buf, '.'))) {
  495. X            *pch = '\000';
  496. X        }
  497. X    }
  498. X
  499. X    /* if this is not a binary dependancy, add a suffix to it
  500. X     */
  501. X    if (1 != file->binarydep) {
  502. X        if (NULL != file->suffix) {
  503. X            strcat(buf, file->suffix);
  504. X        } else {
  505. X            strcat(buf, ".o");
  506. X        }
  507. X    }
  508. X
  509. X    return buf;
  510. }
  511. X
  512. /* DoReplace
  513. X * This is a routine that goes through the current dependancies (if any)
  514. X * and spits out the ones that are NOT being replaced. If the shortening
  515. X * of include file names is turned off, it will spit out the currently
  516. X * defined vars, otherwise, it lets them be rebuilt.
  517. X */
  518. void
  519. DoReplace()
  520. {
  521. X    register DependInfo *pDI;
  522. X    register int found = FALSE, cont = FALSE;
  523. X    register char *fname;
  524. X    register int len;
  525. X    auto char buf[BUFSIZE];
  526. X
  527. X    while (NULL != fgets(buf, BUFSIZE, fpBackup)) {
  528. X        if (FALSE != cont) {
  529. X            if (FALSE == found) {
  530. X                fputs(buf, makefp);
  531. X            }
  532. X            cont = '\\' == buf[strlen(buf) - 2] ? TRUE : FALSE;
  533. X            continue;
  534. X        }
  535. X
  536. X        found = cont = FALSE;
  537. X        if ('\n' == buf[0]) {
  538. X            continue;
  539. X        }
  540. X
  541. X        /* If we are not shortening the include file names on this
  542. X         * replacement, we at least have to spit out the old
  543. X         * abbreviations
  544. X         */
  545. X        if (isupper(buf[0]) && '=' == buf[1]) {
  546. X            fname = strrchr(buf, '\n');
  547. X            if ((char *)0 == fname) {
  548. X                fprintf(stderr, "%s: internal error or line too long\n", progname);
  549. X                RestoreFiles();
  550. X            }
  551. X            *fname = '\000';
  552. X            if (NULL == srtin(&abrv, hincl(buf+2), lngsrt)) {
  553. X                OutOfMemory();
  554. X            }
  555. X            if (FALSE != verbose)
  556. X                fprintf(stderr, "%s: inserted abbr %s\n", progname, buf+2);
  557. X        } else {
  558. X            for (pDI = FileInfo.next; NULL != pDI; pDI = pDI->next) {
  559. X                fname = DestName(pDI);
  560. X                len = strlen(fname);
  561. X                found = (':' == buf[len] &&
  562. X                   0 == strncmp(fname, buf, len))? TRUE: FALSE;
  563. X                if (found)
  564. X                    break;
  565. X            }
  566. X            if (FALSE == found && '#' != buf[0]) {
  567. X                fputc('\n', makefp);
  568. X                fputs(buf, makefp);
  569. X            }
  570. X            cont = '\\' == buf[strlen(buf) - 2] ? TRUE : FALSE;
  571. X        }
  572. X    }
  573. }
  574. X
  575. /*
  576. X * output a user rule expanded                        (ksb)
  577. X */
  578. void
  579. expand(src, pDI, fpTo)
  580. char *src;
  581. DependInfo *pDI;
  582. FILE *fpTo;
  583. {
  584. X    register int i, num;
  585. X    register char chLast = '\n';
  586. X    register char *pc;
  587. X    auto char acf[1025];
  588. X    auto char acF[1025];
  589. X    auto char
  590. X        *tp,    /* the / in %o/%t%s        */
  591. X        *sp,    /* the . in %s, or a "\000"    */
  592. X        *Tp,    /* the / in %o/%t%s        */
  593. X        *Sp;    /* the . in %s, or a "\000"    */
  594. X
  595. X    pc = strrchr(pDI->filename, '/');
  596. X    if ((char *)0 == pc) {
  597. X        strcpy(acf, ".");
  598. X        strcpy(acF, ".");
  599. X    } else {
  600. X        *pc = '\000';
  601. X        strcpy(acf, pDI->filename);
  602. X        strcpy(acF, pDI->filename);
  603. X        *pc = '/';
  604. X    }
  605. X    if ((char *)0 != pDI->destdir) {
  606. X        strcpy(acf, pDI->destdir);
  607. X    }
  608. X
  609. X    tp = strrchr(acf, '\000');
  610. X    tp[0] =  '/';
  611. X    Tp = strrchr(acF, '\000');
  612. X    Tp[0] =  '/';
  613. X    if ((char *)0 == pc) {
  614. X        strcpy(tp+1, pDI->filename);
  615. X        strcpy(Tp+1, pDI->filename);
  616. X    } else {
  617. X        strcpy(tp+1, pc+1);
  618. X        strcpy(Tp+1, pc+1);
  619. X    }
  620. X    if ((char *)0 != pDI->basename) {
  621. X        strcpy(tp+1, pDI->basename);
  622. X    }
  623. X
  624. X    sp = strrchr(tp, '.');
  625. X    if ((char *)0 == sp)
  626. X        sp = strrchr(tp, '\000');
  627. X    Sp = strrchr(Tp, '.');
  628. X
  629. X    if ((char *)0 != pDI->suffix) {
  630. X        strcpy(sp, pDI->suffix);
  631. X    } else if (1 == pDI->binarydep) {
  632. X        sp[0] = '\000';
  633. X    } else {
  634. X        strcpy(sp, ".o");
  635. X    }
  636. X
  637. X    while (*src) {
  638. X        if ('\n' == chLast) {
  639. X            if (makefp == fpTo)    /* ZZZ hack */
  640. X                putc('\t', fpTo);
  641. X        }
  642. X        chLast = *src;
  643. X        switch (*src) {
  644. X        case '%':
  645. X            /* %f: %F
  646. X             * %o/%t.%s: %O/%T.%S
  647. X             * %%
  648. X             */
  649. X            switch (*++src) {
  650. X            /* target */
  651. X            case 'o':    /* directory part    */
  652. X                *tp = '\000';
  653. X                fputs(acf, fpTo);
  654. X                *tp = '/';
  655. X                break;
  656. X
  657. X            case 't':
  658. X                if ('\000' == *sp) {
  659. X                    fputs(tp+1, fpTo);
  660. X                } else {
  661. X                    i = *sp;
  662. X                    *sp = '\000';
  663. X                    fputs(tp+1, fpTo);
  664. X                    *sp = i;
  665. X                }
  666. X                break;
  667. X
  668. X            case 's':
  669. X                fputs(sp, fpTo);
  670. X                break;
  671. X
  672. X            case 'f':
  673. X                fputs(acf, fpTo);
  674. X                break;
  675. X
  676. X            /* source */
  677. X            case 'O':
  678. X                *Tp = '\000';
  679. X                fputs(acF, fpTo);
  680. X                *Tp = '/';
  681. X                break;
  682. X
  683. X            case 'T':
  684. X                if ((char *)0 == Sp) {
  685. X                    fputs(Tp+1, fpTo);
  686. X                } else {
  687. X                    *Sp = '\000';
  688. X                    fputs(Tp+1, fpTo);
  689. X                    *Sp = '.';
  690. X                }
  691. X                break;
  692. X
  693. X            case 'S':
  694. X                if ((char *)0 != Sp)
  695. X                    fputs(Sp, fpTo);
  696. X                break;
  697. X
  698. X            case 'F':
  699. X                fputs(acF, fpTo);
  700. X                break;
  701. X
  702. X            /* global */
  703. X            case 'L':
  704. X                if ((char *)0 != pDI->inlib)
  705. X                    fputs(pDI->inlib, fpTo);
  706. X                break;
  707. X
  708. X            case 'I':
  709. X                if ((char *)0 != pDI->cppflags)
  710. X                    fputs(pDI->cppflags, fpTo);
  711. X                break;
  712. X
  713. X            case '%':
  714. X            default:    /* unrecognized chars are copied thru */
  715. X                fputc(*src, fpTo);
  716. X                break;
  717. X            }
  718. X            src++;
  719. X            break;
  720. X
  721. X        case '\\':
  722. X            switch (*++src) {
  723. X            case '\n':    /* how would this happen? */
  724. X                ++src;
  725. X                break;
  726. X            case 'a':
  727. X                fputc('\007', fpTo);
  728. X                ++src;
  729. X                break;
  730. X            case 'n':    /* newline */
  731. X                fputc('\n', fpTo);
  732. X                chLast = '\n';
  733. X                ++src;
  734. X                break;
  735. X            case 't':
  736. X                fputc('\t', fpTo);
  737. X                ++src;
  738. X                break;
  739. X            case 'b':
  740. X                fputc('\b', fpTo);
  741. X                ++src;
  742. X                break;
  743. X            case 'r':
  744. X                fputc('\r', fpTo);
  745. X                ++src;
  746. X                break;
  747. X            case 'f':
  748. X                fputc('\f', fpTo);
  749. X                ++src;
  750. X                break;
  751. X            case 'v':
  752. X                fputc('\013', fpTo);
  753. X                ++src;
  754. X                break;
  755. X            case '\\':
  756. X                ++src;
  757. X            case '\000':
  758. X                fputc('\\', fpTo);
  759. X                break;
  760. X
  761. X            case '0': case '1': case '2': case '3':
  762. X            case '4': case '5': case '6': case '7':
  763. X                num = *src++ - '0';
  764. X                for (i = 0; i < 2; i++) {
  765. X                    if (! isdigit(*src)) {
  766. X                        break;
  767. X                    }
  768. X                    num <<= 3;
  769. X                    num += *src++ - '0';
  770. X                }
  771. X                fputc(num, fpTo);
  772. X                chLast = num;
  773. X                break;
  774. X            case '8': case '9':
  775. X                /* 8 & 9 are bogus octals,
  776. X                 * cc makes them literals
  777. X                 */
  778. X                /*fallthrough*/
  779. X            default:
  780. X                fputc(*src++, fpTo);
  781. X                break;
  782. X            }
  783. X            break;
  784. X        default:
  785. X            fputc(*src, fpTo);
  786. X            src++;
  787. X            break;
  788. X        }
  789. X    }
  790. X
  791. X    if ('\n' != chLast)
  792. X        fputc('\n', fpTo);
  793. }
  794. X
  795. /* generate the depend info for a given file
  796. X */
  797. void
  798. DoDepend(file)
  799. DependInfo *file;
  800. {
  801. X    register int lineend, i;
  802. X    register char *p, *q, *name;
  803. X    auto int complen;
  804. X    auto char ppbuf[BUFSIZE], buf[BUFSIZE];
  805. X    auto char acFile[1025];
  806. X    auto FILE *fpCmd;
  807. X
  808. X    /* compute the dest name and save it, we want this one for a while
  809. X     */
  810. X    name = DestName(file);
  811. X    name = STRSAVE(name);
  812. X    if (FALSE != verbose)
  813. X        fprintf(stderr, "%s: working on %s\n", progname, name);
  814. X
  815. X    /* with the help of a little conditional compilation
  816. X     * set up the command string
  817. X     */
  818. X    mktemp(strcpy(acFile, "/tmp/mtdXXXXXX"));
  819. X    if (NULL == (fpCmd = fopen(acFile, "w"))) {
  820. X        fprintf(stderr, "%s: fopen: %s: %s\n", progname, acFile, strerror(errno));
  821. X        RestoreFiles();
  822. X    }
  823. X    expand(file->preprocessor, file, fpCmd);
  824. X    fclose(fpCmd);
  825. X
  826. X    if (FALSE != verbose) {
  827. X        fprintf(stderr, "%s: shell command: (in %s)\n", progname, acFile);
  828. X        sprintf(buf, "cat %s", acFile);
  829. X        system(buf);
  830. X    }
  831. X
  832. X    (void)sprintf(buf, "sh <%s", acFile);
  833. X    if (NULL == (fpPipe = popen(buf, "r"))) {
  834. X        fprintf(stderr, "%s: popen: %s: %s\n", progname, buf, strerror(errno));
  835. X        RestoreFiles();
  836. X    }
  837. X
  838. X    /* Start with a fresh list of dependancy files */
  839. X    srtfree(&incld);
  840. X
  841. X    while (NULL != fgets(ppbuf, BUFSIZE, fpPipe)) {
  842. X        if (NULL == (p = strchr(ppbuf, ':'))) {
  843. X            fprintf(stderr, "%s: preprocessor output missing colon\n", progname);
  844. X            RestoreFiles();
  845. X        }
  846. X        ++p;    /* Get past colon */
  847. X        if (' ' != *p++) {
  848. X            fprintf(stderr, "%s: preprocessor output missing space\n", progname);
  849. X            RestoreFiles();
  850. X        }
  851. X
  852. X        /* Make pathname pretty */
  853. X        p = hincl(p);
  854. X
  855. X        /* Replace newline with a null */
  856. X        if (NULL != (q = strchr(p, '\n')))
  857. X            *q = '\000';
  858. X
  859. X        /* If all dependancies are NOT to be made, skip over
  860. X         * the basic include path
  861. X         */
  862. X        if (FALSE == alldep && 0 == strncmp(sbInc, p, sizeof(sbInc)-1))
  863. X            continue;
  864. X
  865. X        /* Insert it into our list */
  866. X        if (NULL == srtin(&incld, p, strcmp)) {
  867. X            OutOfMemory();
  868. X        }
  869. X        if (FALSE != verbose)
  870. X            fprintf(stderr, "%s: inserted %s\n", progname, p);
  871. X    }
  872. #if 0
  873. X    while (NULL != fgets(ppbuf, BUFSIZE, fpPipe)) {
  874. X        /* An include statement starts with a # */
  875. X        if ('#' != ppbuf[0])
  876. X            continue;
  877. X        
  878. X        /* eat #ident lines (mostly a sysv thing) */
  879. X        p = ppbuf;
  880. X        do {
  881. X            ++p;
  882. X        } while (' ' == *p || '\t' == *p);
  883. X        if (! isdigit(*p)) {
  884. X            continue;
  885. X        }
  886. X
  887. X        /* Find the first double quote and go one past it */
  888. X        if (NULL == (p = strchr(p, '"')))
  889. X            continue;
  890. X        ++p;
  891. X
  892. X        /* Make the path pretty */
  893. X        p = hincl(p);
  894. X
  895. X        if (NULL != (q = strchr(p, '"')))
  896. X            *q = '\000';
  897. X
  898. X        /* If all dependancies are NOT to be made, skip over
  899. X         * the basic include path
  900. X         */
  901. X        if (FALSE == alldep && 0 == strncmp(sbInc, p, sizeof(sbInc)-1))
  902. X            continue;
  903. X
  904. X        /* Insert it into our list */
  905. X        if (NULL == srtin(&incld, p, strcmp))
  906. X            OutOfMemory();
  907. X        if (FALSE != verbose)
  908. X            fprintf(stderr, "%s: inserted %s\n", progname, p);
  909. X    }
  910. #endif /* need to look at raw cpp output */
  911. X
  912. X    /* Initialize so we can use srtgets */
  913. X    srtgti(&incld);
  914. X
  915. X    lineend = MAXCOL+1;        /* Force a newline in the output */
  916. X    /* Write out the entries */
  917. X    while (NULL != (p = srtgets(&incld))) {
  918. X        /* set i = found index or MXABR */
  919. X        if (FALSE != shortincl && MXABR != (i = findabr(p))) {
  920. X            p += abrvlen[i];
  921. X            if ('/' != p[0] && '\000' != p[0]) {
  922. X                complen = 4;
  923. X            } else {
  924. X                complen = 2;
  925. X            }
  926. X        } else {
  927. X            complen = 0;
  928. X        }
  929. X
  930. X        complen += strlen(p);
  931. X        if (MAXCOL <= lineend + complen) {
  932. X            if ((char *)0 != name) {
  933. X                /* 2 for the colon and space */
  934. X                lineend = strlen(name) + 2;
  935. X                if ((char *)0 != file->inlib) {
  936. X                    /* + parens  and lib name */
  937. X                    lineend += 2 + strlen(file->inlib);
  938. X                    fprintf(makefp, "\n%s(%s): ", file->inlib, name);
  939. X                } else {
  940. X                    fprintf(makefp, "\n%s: ", name);
  941. X                }
  942. X                free(name);
  943. X                name = (char *) 0;
  944. X                if (MAXCOL <= lineend + complen) {
  945. X                    lineend = 8;
  946. X                    fprintf(makefp, "\\\n\t");
  947. X                }
  948. X            } else {
  949. X                lineend = 8;
  950. X                fprintf(makefp, " \\\n\t");
  951. X            }
  952. X        } else {
  953. X            ++lineend;
  954. X            fputc(' ', makefp);
  955. X        }
  956. X
  957. X        if (FALSE != shortincl && MXABR != i) {
  958. X            if ('/' != p[0] && '\000' != p[0]) {
  959. X                fprintf(makefp, "${%c}", 'A' + i);
  960. X            } else {
  961. X                fprintf(makefp, "$%c", 'A' + i);
  962. X            }
  963. X        }
  964. X        fputs(p, makefp);
  965. X        lineend += complen;
  966. X    }
  967. X    fputc('\n', makefp);
  968. X    pclose(fpPipe);
  969. X    (void)unlink(acFile);
  970. X    if ((char *)0 != file->explicit) {
  971. X        expand(file->explicit, file, makefp);
  972. X    }
  973. }
  974. X
  975. /* DoInit
  976. X * Initialize the signal catching routines
  977. X * and abreviation list
  978. X */
  979. int
  980. DoInit()
  981. {
  982. X    init_sigs();
  983. X    srtinit(&abrv);
  984. }
  985. X
  986. /* MakeTD
  987. X * This part is the actual work-horse of the program. All of the options
  988. X * have been processed at this point, and all we have to do is interpret
  989. X * their meanings
  990. X */
  991. int
  992. MakeTD()
  993. {
  994. X    register DependInfo *pDI;
  995. X    register int fCont;
  996. X    register char *pchTemp;
  997. X    auto char sbLine[BUFSIZE];
  998. X    auto struct stat stOld;
  999. X
  1000. X    /* Find out which makefile is to be used. First, if the user
  1001. X     * specifies a makefile, use that. If he doesn't, check and
  1002. X     * see if 'makefile' exists. Finally, if that doesn't check
  1003. X     * out, see if 'Makefile' exists.
  1004. X     */
  1005. X    if (NULL == makename) {
  1006. X        makename = STRSAVE("makefile");
  1007. X        if (0 != access(makename, F_OK)) {
  1008. X            makename[0] = 'M';
  1009. X            if (0 != access(makename, F_OK)) {
  1010. X                fprintf(stderr, "%s: cannot find makefile\n", progname);
  1011. X                exit(1);
  1012. X            }
  1013. X        }
  1014. X    } else {
  1015. X        if (0 != access(makename, F_OK)) {
  1016. X            fprintf(stderr, "%s: access: %s: %s\n", progname, makename, strerror(errno));
  1017. X            exit(1);
  1018. X        }
  1019. X    }
  1020. X
  1021. X    /* Now backup the makefile to a backup file and unlink the current one
  1022. X     */
  1023. X    if (FALSE == use_stdout) {
  1024. X        BackUp();
  1025. X    } else {
  1026. X        pchBackup = makename;
  1027. X    }
  1028. X    stat(pchBackup, &stOld);
  1029. X
  1030. X    /* Now open the destination makefile, copy over all of the current
  1031. X     * makefile up to the '# DO NOT DELETE THIS LINE' line (or the
  1032. X     * end-of-file, whichever comes first), and then continue with
  1033. X     * processing.
  1034. X     */
  1035. X    if (NULL == (fpBackup = fopen(pchBackup, "r"))) {
  1036. X        fprintf(stderr, "%s: fopen: %s: %s\n", progname, pchBackup, strerror(errno));
  1037. X        RestoreFiles();
  1038. X    }
  1039. X
  1040. X    if (FALSE != use_stdout) {
  1041. X        makefp = stdout;
  1042. X    } else if (NULL == (makefp = fopen(makename, "w"))) {
  1043. X        fprintf(stderr, "%s fopen: %s: %s\n", progname, makename, strerror(errno));
  1044. X        RestoreFiles();
  1045. X    } else {
  1046. X        /* chmod the Makefile */
  1047. X        if (-1 == chmod(makename, (stOld.st_mode & 07777))) {
  1048. X            fprintf(stderr, "%s: chmod: %s: %s\n", progname, makename, strerror(errno));
  1049. X            RestoreFiles();
  1050. X        }
  1051. X    }
  1052. X
  1053. X    /* clever use of continuations used to hose us over
  1054. X     */
  1055. X    fCont = FALSE;
  1056. X    while (NULL != fgets(sbLine, BUFSIZE, fpBackup) && (FALSE != fCont ||
  1057. X        0 != strncmp(searchdep, sbLine, strlen(searchdep)))) {
  1058. X        pchTemp = strrchr(sbLine, '\\');
  1059. X        if ((char *)0 != pchTemp && '\n' == pchTemp[1]) {
  1060. X            fCont = TRUE;
  1061. X        } else {
  1062. X            if (FALSE == fCont)
  1063. X                srchincl(sbLine);
  1064. X
  1065. X            fCont = FALSE;
  1066. X        }
  1067. X        if (FALSE == use_stdout)
  1068. X            (void)fputs(sbLine, makefp);
  1069. X    }
  1070. X
  1071. X    /* If we need the header put in, do it now
  1072. X     */
  1073. X    if (FALSE == use_stdout || FALSE != force_head) {
  1074. X        (void)fputs(deplin, makefp);
  1075. X    }
  1076. X
  1077. X    /* Put out the abbreviations table
  1078. X     */
  1079. X    if (FALSE != alldep) {
  1080. X        sprintf(sbLine, "%s/sys", sbInc);
  1081. X        if (FALSE != verbose)
  1082. X            fprintf(stderr, "%s: all depends inserts %s and %s\n", progname, sbInc, sbLine);
  1083. X        if (NULL == srtin(&abrv, hincl(sbInc), lngsrt) ||
  1084. X            NULL == srtin(&abrv, hincl(sbLine), lngsrt)) {
  1085. X            OutOfMemory();
  1086. X        }
  1087. X    }
  1088. X
  1089. X    if (FALSE != shortincl) {
  1090. X        abrvsetup();
  1091. X    }
  1092. X
  1093. X    /* Check to see if we have to replace the files instead of just
  1094. X     * recreating all dependancies
  1095. X     */
  1096. X    if (FALSE != replace && FALSE == use_stdout) {
  1097. X        DoReplace();
  1098. X    }
  1099. X
  1100. X    /* Now, after we have done everything that needs to be done except
  1101. X     * putting out the dependancies for the list of files we have, lets
  1102. X     * go ahead and do that! First we have to initialize our sorted
  1103. X     * list.
  1104. X     */
  1105. X    srtinit(&incld);    /* Initialize sorted list of files */
  1106. X    for (pDI = FileInfo.next ; NULL != pDI; pDI = pDI->next) {
  1107. X        DoDepend(pDI);
  1108. X    }
  1109. X
  1110. X    /* Put out the trailer if needed
  1111. X     */
  1112. X    if (FALSE == use_stdout || FALSE != force_head) {
  1113. X        fputs(trailer, makefp);
  1114. X    }
  1115. X
  1116. #ifdef DEL_BACKUP
  1117. X    if (FALSE != backedup && 0 != unlink(backupfn)) {
  1118. X        fprintf(stderr, "%s: unlink: %s: %s\n", progname, pchBackup, strerror(errno));
  1119. X        exit(1);
  1120. X    }
  1121. #endif /* DEL_BACKUP */
  1122. X    exit(0);
  1123. }
  1124. Purdue
  1125. chmod 0444 maketd/maketd.c ||
  1126. echo 'restore of maketd/maketd.c failed'
  1127. Wc_c="`wc -c < 'maketd/maketd.c'`"
  1128. test 21424 -eq "$Wc_c" ||
  1129.     echo 'maketd/maketd.c: original size 21424, current size' "$Wc_c"
  1130. fi
  1131. # ============= maketd/maketd.1l ==============
  1132. if test -f 'maketd/maketd.1l' -a X"$1" != X"-c"; then
  1133.     echo 'x - skipping maketd/maketd.1l (File already exists)'
  1134. else
  1135. echo 'x - extracting maketd/maketd.1l (Text)'
  1136. sed 's/^X//' << 'Purdue' > 'maketd/maketd.1l' &&
  1137. .\" by Kevin Braunsdorf
  1138. .\" $Laser: tbl %f | ltroff -man
  1139. .TH MAKETD 1L PUCC
  1140. .SH NAME
  1141. maketd \- edit a makefile to update transitive dependencies
  1142. .SH SYNOPSIS
  1143. \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]
  1144. .SH DESCRIPTION
  1145. .B Maketd
  1146. computes dependencies for targets that are introduced through the
  1147. C preprocessor's (cpp) \fI#include\fP directive.
  1148. The development of this program resulted from
  1149. .IR make ( 1 )'s
  1150. inability to recognize transitive dependencies.  For example,
  1151. given the following makefile fragment:
  1152. .sp 1
  1153. X    xx.o: xx.c e.h
  1154. .sp 1
  1155. X    e.h: struct.h /usr/include/local/const.h
  1156. .sp 1
  1157. \fIMake\fP will not recognize the target xx.o's dependency on struct.h.
  1158. \fIMaketd\fP generates lines like:
  1159. .sp 1
  1160. X    xx.o: xx.c e.h struct.h $L/const.h
  1161. .sp 1
  1162. Thus making the target xx.o not only dependent on all files that it includes,
  1163. but also recursively on all files that the included files include.
  1164. This is achieved by passing the source through the C preprocessor
  1165. (\fI/bin/cc\fP \-\fIM\fP).
  1166. .PP
  1167. The directories used in the search for include files
  1168. are identical to the ones used by the C compiler because the
  1169. C preprocessor is used.  This also means that 
  1170. .IR #define 's, 
  1171. .IR #ifdef 's, 
  1172. etc., are evaluated.
  1173. It is necessary to recompute the dependencies when any source has been changed.
  1174. The generated dependencies will be inserted after a line of the form 
  1175. \*(lq# DO NOT DELETE...\*(rq (which will be inserted if \fBmaketd\fP
  1176. finds the end of file).
  1177. Everything after this line may be deleted or changed as \fBmaketd\fP edits
  1178. the \fImakefile\fP (the portion of the makefile before this line is only
  1179. examined for context).
  1180. If no such line exists, a line of the expected form will be emitted,
  1181. followed by the dependencies.
  1182. .PP
  1183. By default \fBmaketd\fP will search for the \fImakefile\fP
  1184. to be edited in the same way \fImake\fP does; that is by first checking
  1185. for the existence of \*(lqmakefile\*(rq, then \*(lqMakefile\*(rq.
  1186. The \-\fBm\fP and \-\fBd\fP options override this default action (below).
  1187. Before it is edited, \fImakefile\fP will be saved in
  1188. \*(lq\fImakefile\fP.\fIextend\fP\*(rq
  1189. (overwriting any existing file with the same name).
  1190. This \fIextender\fP on the old version of \fImakefile\fP may
  1191. be changed by using the \-\fBj\fP option (below).
  1192. .SH OPTIONS
  1193. .PP
  1194. Options and arguments may be intermixed on the command line to modify
  1195. \fBmaketd\fP's behavior on a per file basis.
  1196. .TP
  1197. .BI \-4
  1198. Use 
  1199. .IR m4 ( 1 )
  1200. as the preprocessor rather than 
  1201. .IR cc ( 1 ) .  
  1202. This requires that modifications have been made to m4 and that 
  1203. this program be compiled with CPP_M defined.  Use \*(lqmaketd \-h\*(rq 
  1204. to check this.
  1205. .TP
  1206. .BI \-a
  1207. Normally, dependencies on files in \*(lq/usr/include\*(rq are
  1208. not included.  This option also includes dependencies on those files.
  1209. This option should always be used for system level makefiles.
  1210. .TP
  1211. .BI \-b
  1212. Generate dependencies for binaries rather than object files.
  1213. This is equivalent to specifying a null suffix:  the \*(lq.o\*(rq 
  1214. is stripped from the target.
  1215. .TP
  1216. .BI \-c
  1217. Use cc to generate dependencies (rather than m4).  This is the default.
  1218. .TP
  1219. .BI \-d
  1220. Dependencies are written to standard output instead of editing a makefile.
  1221. The standard header and trailer, \*(lq# DO NOT DELETE...\*(rq are not printed.
  1222. .\".TP
  1223. .\".BI \-e rule
  1224. .\"The given \fIrule\fP is ouptut under each of the following \fIfile\fP's
  1225. .\"dependency lists.
  1226. .\"For \fIprintf\fP-like percent (%) escapes are expanded to allow the
  1227. .\"user to customize the rule.
  1228. .\".sp 1
  1229. .\".RS
  1230. .\".TS
  1231. .\"l l l.
  1232. .\"escape  expands
  1233. .\"%    a percent
  1234. .\"F    the source file
  1235. .\"I    the \fIcpp\fP flags for this file
  1236. .\"O    the source dir
  1237. .\"S    the source suffix
  1238. .\"L    the library containing this file
  1239. .\"T    the source basename
  1240. .\"f    the full target file
  1241. .\"o    the target dir (set by \-\fBo\fP)
  1242. .\"s    the target suffix (set by \-\fBs\fP)
  1243. .\"t    the target base name (set by \-\fBt\fP)
  1244. .\".TE
  1245. .\".RE
  1246. .TP
  1247. .BI \-f
  1248. Force printing of header and trailer.
  1249. Normally these are suppressed when the output file is the standard output.
  1250. .TP
  1251. .BI \-h
  1252. Only output a usage summary.
  1253. .TP
  1254. .BI \-j extender
  1255. Specify an extension for the backup makefile, rather than the default 
  1256. \*(lqbak\*(rq extender.
  1257. .TP
  1258. .BI \-l
  1259. Turn off the nonlocal object option, and make all targets local.
  1260. .TP
  1261. .BI \-m makefile
  1262. Instead of editing \*(lqmakefile\*(rq, \fImakefile\fP is edited.
  1263. .TP
  1264. .BI \-n
  1265. Generate nonlocal object dependency paths.
  1266. These paths will match the source paths given.
  1267. .TP
  1268. .BI \-o dir
  1269. Generate nonlocal object dependencies in the specified \fIdir\fP.
  1270. This option generates dependencies of the form
  1271. .sp 1
  1272. X    \fIdir\fP/a.o: a.c
  1273. .sp 1
  1274. which is useful for makefiles that produce the objects in
  1275. a separate subdirectory.
  1276. The name of the directory must not be empty (see \-\fBl\fP above).
  1277. .TP
  1278. .BI \-r
  1279. Replace the dependencies for the target(s) mentioned on the command line.
  1280. Do not alter any other dependencies that may have been in \fImakefile\fP.
  1281. This option is of limited use and unlimited misuse: beware.
  1282. .TP
  1283. .BI \-s suffix
  1284. Supply a suffix for the target.  The \fIsuffix\fP should
  1285. start with a \*(lq.\*(rq.
  1286. The target file name should have a suffix of some sort that
  1287. is delimited by a \*(lq.\*(rq that is replaced by this suffix.
  1288. .TP
  1289. .BI \-t target
  1290. Supply a new basename for the target rather than using the basename of the
  1291. source file.
  1292. .TP
  1293. .BI \-v
  1294. Be verbose.
  1295. Extra output is directed to the standard error channel.
  1296. .TP
  1297. .BI \-V
  1298. Show which version of \fImaketd\fP is running.
  1299. .TP
  1300. .BI \-x
  1301. Do not shorten include files.
  1302. The pathnames \*(lq/usr/include\*(rq and \*(lq/usr/include/sys\*(rq
  1303. along with any pathnames specified with the \-I options, are abbreviated.
  1304. Unused uppercase single letters are defined in \fImakefile\fP and used to
  1305. compress pathnames.
  1306. .TP
  1307. .BI \-C
  1308. Cancel all previous cpp flags (\-\fBD\fP, \-\fBI\fP, and \-\fBU\fP)
  1309. and begin a new list.  This is useful for generating
  1310. dependencies for more than one product with only one \fBmaketd\fP call.
  1311. .TP
  1312. .BI \-D define
  1313. Specify a cpp (C preprocessor) definition.  See
  1314. .IR cc ( 1 ).
  1315. for a complete description.
  1316. .\".TP
  1317. .\".BI \-E
  1318. .\"Cancel an explicit \fIrule\fP given by \-\fBe\fP.
  1319. .\".TP
  1320. .\".BI \-F gen-dep
  1321. .\"The \fIgen-dep\fP shell command is expanded as a \-e \fIrule\fP would be
  1322. .\"and given to the shell.  The resulting output must look like the
  1323. .\"output of \fIcpp\fP \fI\-M\fP, that is contain only lines of the form:
  1324. .\".sp 1
  1325. .\"    \fItarget\fP\fB: \fP\fIdep\fP
  1326. .\".sp 1
  1327. .\"which should list of all the \fIdeps\fP on which \fItarget\fP
  1328. .\"depends one per line.
  1329. .TP
  1330. .BI \-I includedir
  1331. Specify a directory for cpp to search for include files.
  1332. See
  1333. .IR cc ( 1 )
  1334. for a complete description.
  1335. Note that \fIincludedir\fP is subject to abbreviation unless \-\fBx\fP is
  1336. given.
  1337. .TP
  1338. .BI \-L lib.a
  1339. This option produces a dependency that tells \fImake\fP(1) that the
  1340. target is part of \fIlib.a\fP.
  1341. .TP
  1342. .BI \-U name
  1343. Remove any initial definition of the (C preprocessor) variable
  1344. .IR name .
  1345. .SH EXAMPLES
  1346. A typical application in a makefile might look like:
  1347. .sp 1
  1348. .RS
  1349. .nf
  1350. L=/usr/include/local
  1351. INCLUDE=  \-I$L \-I../h
  1352. CDEFS=    \-DPUCC \-DBSD4_2
  1353. CFLAGS=    ${DEFS} ${INCLUDE}
  1354. X
  1355. SRC=    a.c b.c c.c
  1356. HDR=    a.h b.h c.h
  1357. X
  1358. \&. . .
  1359. depend: ${SRC} ${HDR}
  1360. X    maketd \-a ${CDEFS} ${INCLUDE} ${SRC}
  1361. X
  1362. # DO NOT DELETE THIS LINE \- maketd DEPENDS ON IT
  1363. X
  1364. a.o: a.c a.h b.h c.h $L/goop.h
  1365. X
  1366. b.o: b.c b.h $L/goop.h
  1367. X
  1368. c.o: c.c c.h
  1369. X
  1370. # *** Do not add anything here \- It will go away. ***
  1371. .fi
  1372. .RE
  1373. .sp 1
  1374. .SH BUGS
  1375. .PP
  1376. If a single letter macro name is used but never defined (in the makefile)
  1377. \fBmaketd\fP might still use it for an abbreviation name.  This should not
  1378. effect the makefile as all the dependencies and the redefinition of the
  1379. macro will follow the users last usage of it.  This happens in DYNIX makefiles
  1380. that use \*(lqP\*(rq to indicate that parallel compilation should be used.
  1381. We suggest that Makefiles which use this trick put a
  1382. .sp 1
  1383. X    P=
  1384. .sp 1
  1385. in the Makefile (above the all target) to keep \fImaketd\fP from using
  1386. the macro \*(lqP\*(rq; the command line definition of P="&" will override
  1387. the Makefile's definition.
  1388. .PP
  1389. Some more path compression could be done.
  1390. .SH AUTHORS
  1391. Stephan Bechtolsheim (a shell script), Purdue CS
  1392. .br
  1393. Stephen Uitti (a C version), Purdue CC
  1394. .br
  1395. Craig Norborg (m4 modifications), Purdue CC
  1396. .br
  1397. Kevin Braunsdorf (intermix options), Purdue CC
  1398. .SH SEE ALSO
  1399. make(1), cc(1), m4(1)
  1400. Purdue
  1401. chmod 0444 maketd/maketd.1l ||
  1402. echo 'restore of maketd/maketd.1l failed'
  1403. Wc_c="`wc -c < 'maketd/maketd.1l'`"
  1404. test 8481 -eq "$Wc_c" ||
  1405.     echo 'maketd/maketd.1l: original size 8481, current size' "$Wc_c"
  1406. fi
  1407. # ============= libopt/libopt.3l ==============
  1408. if test ! -d 'libopt'; then
  1409.     echo 'x - creating directory libopt'
  1410.     mkdir 'libopt'
  1411. fi
  1412. if test -f 'libopt/libopt.3l' -a X"$1" != X"-c"; then
  1413.     echo 'x - skipping libopt/libopt.3l (File already exists)'
  1414. else
  1415. echo 'x - extracting libopt/libopt.3l (Text)'
  1416. sed 's/^X//' << 'Purdue' > 'libopt/libopt.3l' &&
  1417. .\" Copyright (c) 1988 Regents of the University of California.
  1418. .\" All rights reserved.
  1419. .\"
  1420. .\" Redistribution and use in source and binary forms are permitted
  1421. .\" provided that the above copyright notice and this paragraph are
  1422. .\" duplicated in all such forms and that any documentation,
  1423. .\" advertising materials, and other materials related to such
  1424. .\" distribution and use acknowledge that the software was developed
  1425. .\" by the University of California, Berkeley.  The name of the
  1426. .\" University may not be used to endorse or promote products derived
  1427. .\" from this software without specific prior written permission.
  1428. .\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  1429. .\" IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  1430. .\" WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  1431. .\"
  1432. .\"    @(#)getopt.3    6.8 (Berkeley) 7/9/88
  1433. .\"
  1434. .TH LIBOPT 3L "June 1990"
  1435. .UC 6
  1436. .SH NAME
  1437. envopt, getopt, getarg, optind, optarg, optsil, rescan \- process a command line
  1438. .SH SYNOPSIS
  1439. #include \*(lqgetopt.h\*(rq
  1440. .sp
  1441. .ft B
  1442. int getopt(argc, argv, optstring)
  1443. .br
  1444. int argc;
  1445. .br
  1446. char **argv;
  1447. .br
  1448. char *optstring;
  1449. .sp
  1450. int getarg(argc, argv)
  1451. .br
  1452. int argc;
  1453. .br
  1454. char **argv;
  1455. .sp
  1456. envopt(toscan)
  1457. .br
  1458. char *toscan;
  1459. .sp
  1460. extern char *optarg;
  1461. .br
  1462. extern int optind;
  1463. .br
  1464. extern int optsil;
  1465. .sp
  1466. int rescan()
  1467. .ft
  1468. .sp 1
  1469. cc -I/usr/include/local -o tool ... -lopt
  1470. .SH DESCRIPTION
  1471. .I Getopt
  1472. returns the next option letter in
  1473. .I argv
  1474. that matches a letter in
  1475. .IR optstring .
  1476. .I Optstring
  1477. is a string of recognized option letters;
  1478. if a letter is followed by a colon, the option is expected to have
  1479. an argument that may or may not be separated from it by white space.
  1480. .I Optarg
  1481. is set to point to the start of the option argument on return from
  1482. .IR getopt .
  1483. .PP
  1484. .I Getopt
  1485. places in
  1486. .I optind
  1487. the
  1488. .I argv
  1489. index of the next argument to be processed.
  1490. Because
  1491. .I optind
  1492. is external, it is normally initialized to zero automatically
  1493. before the first call to 
  1494. .IR getopt .
  1495. .PP
  1496. When all options have been processed (i.e., up to the first
  1497. non-option argument),
  1498. .I getopt
  1499. returns
  1500. .BR EOF .
  1501. The special option
  1502. .B \-\-
  1503. may be used to delimit the end of the options;
  1504. .B EOF
  1505. will be returned, and
  1506. .B \-\-
  1507. will be skipped.
  1508. .PP
  1509. After
  1510. .IR getopt
  1511. has returned an EOF
  1512. .IR getarg
  1513. may be called to extract the remaining arguments from the command line
  1514. one at a time.
  1515. .PP
  1516. If another scan of the argument list is required the function
  1517. .IR rescan ()
  1518. may be called to reset the index into the option list.
  1519. .PP
  1520. If an environment variable is read as options to the program its
  1521. value must be passed to
  1522. .IR envopt
  1523. before the first call the
  1524. .IR getopt .
  1525. .SH DIAGNOSTICS
  1526. .I Getopt
  1527. prints an error message on
  1528. .I stderr
  1529. and returns a question mark
  1530. .RB ( ? )
  1531. when it encounters an option letter not included in
  1532. .IR optstring .
  1533. Setting \fIopterr\fP to a zero will disable this error message.
  1534. .SH EXAMPLE
  1535. The following code fragment shows how one might process the arguments
  1536. for a command that can take the mutually exclusive options
  1537. .B a
  1538. and
  1539. .BR b ,
  1540. and the options
  1541. .B f
  1542. and
  1543. .BR o ,
  1544. both of which require arguments:
  1545. .PP
  1546. .RS
  1547. .nf
  1548. #include <stdio.h>
  1549. #include "getopt.h"
  1550. X
  1551. main(argc, argv)
  1552. int argc;
  1553. char **argv;
  1554. {
  1555. X    int c;
  1556. X    extern int optind;
  1557. X    extern char *optarg;
  1558. X    extern char *getenv();
  1559. X    char *scanme;
  1560. X    \&.
  1561. X    \&.
  1562. X    \&.
  1563. X    /* option environment variable to read */
  1564. X    if (0 != (scanme = getenv("TRY")))
  1565. X        envopt(scanme);
  1566. X    \&.
  1567. X    \&.
  1568. X    \&.
  1569. X    while ((c = getopt(argc, argv, "abf:o:")) != EOF)
  1570. X        switch (c) {
  1571. X        case `a':
  1572. X            if (bflg)
  1573. X                errflg++;
  1574. X            else
  1575. X                aflg++;
  1576. X            break;
  1577. X        case `b':
  1578. X            if (aflg)
  1579. X                errflg++;
  1580. X            else
  1581. X                bproc();
  1582. X            break;
  1583. X        case `f':
  1584. X            ifile = optarg;
  1585. X            break;
  1586. X        case `o':
  1587. X            ofile = optarg;
  1588. X            break;
  1589. X        case `?':
  1590. X        default:
  1591. X            errflg++;
  1592. X            break;
  1593. X        }
  1594. X    if (errflg) {
  1595. X        fprintf(stderr, "Usage: ...");
  1596. X        exit(2);
  1597. X    }
  1598. X    while (EOF != getarg(argc, argv))) {
  1599. X        process(optarg);
  1600. X        \&.
  1601. X        \&.
  1602. X        \&.
  1603. X    }
  1604. X    \&.
  1605. X    \&.
  1606. X    \&.
  1607. }
  1608. .RE
  1609. .SH HISTORY
  1610. Written by Henry Spencer, working from a Bell Labs manual page.
  1611. Modified by Keith Bostic to behave more like the System V version.
  1612. Modified by Kevin Braunsdorf to read environment variables.
  1613. .SH BUGS
  1614. ``-'' may be specified as an option letter, however it should never have
  1615. an argument associated with it.  This allows getopt to be used with
  1616. programs that think that ``-'' means standard input.
  1617. .PP
  1618. Option arguments are allowed to begin with ``\-'';
  1619. this is reasonable but reduces the amount of error checking possible.
  1620. .PP
  1621. .I Getopt
  1622. is quite flexible but the obvious price must be paid:  there is much
  1623. it could do that it doesn't, like
  1624. checking mutually exclusive options, checking type of
  1625. option arguments, etc.
  1626. Purdue
  1627. chmod 0444 libopt/libopt.3l ||
  1628. echo 'restore of libopt/libopt.3l failed'
  1629. Wc_c="`wc -c < 'libopt/libopt.3l'`"
  1630. test 4616 -eq "$Wc_c" ||
  1631.     echo 'libopt/libopt.3l: original size 4616, current size' "$Wc_c"
  1632. fi
  1633. # ============= libsrtunq/libsrtunq.3l ==============
  1634. if test ! -d 'libsrtunq'; then
  1635.     echo 'x - creating directory libsrtunq'
  1636.     mkdir 'libsrtunq'
  1637. fi
  1638. if test -f 'libsrtunq/libsrtunq.3l' -a X"$1" != X"-c"; then
  1639.     echo 'x - skipping libsrtunq/libsrtunq.3l (File already exists)'
  1640. else
  1641. echo 'x - extracting libsrtunq/libsrtunq.3l (Text)'
  1642. sed 's/^X//' << 'Purdue' > 'libsrtunq/libsrtunq.3l' &&
  1643. .\"    # my routine titler -- accepts the lines of the title as args
  1644. .de TM
  1645. .in .5i
  1646. .B \\$1
  1647. .br
  1648. .B \\$2
  1649. .br
  1650. .B \\$3
  1651. .br
  1652. .B \\$4
  1653. .br
  1654. .B \\$5
  1655. .br
  1656. .B \\$6
  1657. .br
  1658. .B \\$7
  1659. .br
  1660. .B \\$8
  1661. .br
  1662. .B \\$9
  1663. .br
  1664. .ft R
  1665. .in +.5i
  1666. ..
  1667. '
  1668. '
  1669. '
  1670. .TH SRTUNQ 3L PUCC
  1671. .SH NAME
  1672. srtdel, srtinit, srtin, srtmem, srtgti, srtgets, srtapply, srtfree, srtdtree \- in memory
  1673. string sorting
  1674. .SH SYNOPSIS
  1675. .B #include <stdio.h>
  1676. .br
  1677. .B #include \*(lqsrtunq.h\*(rq
  1678. .sp
  1679. cc \-I/usr/include/local file.c
  1680. .B \-lsrtunq
  1681. .SH DESCRIPTION
  1682. .I Libsrtunq.a
  1683. is used to extract unique items from a possibly long list,
  1684. where items are likely to be replicated numerously.
  1685. The list of unique items must be small enough to
  1686. fit in memory, but the number of repetitions is possibly high.
  1687. .PP
  1688. The caller has control over the database through the use of a
  1689. \fBSRTTABLE\fP variable.  The subroutines provide for data entry and
  1690. retrieval, memory allocation and deallocation.
  1691. .SH ROUTINES
  1692. .TM "typedef  struct ... SRTTABLE;"
  1693. Users will define one variable of this type to hold the root of
  1694. each sorted list they wish to keep.
  1695. Most routines in this library require the address of such
  1696. a variable as their first argument.
  1697. X
  1698. .TM "typedef  struct ... SRTENTRY;"
  1699. Strings are kept in a structure of this type internally.
  1700. The user should not depend on the internal details of this type.
  1701. X
  1702. .TM "void" "srtinit(tbl)" "SRTTABLE *tbl;"
  1703. This subroutine must be called to initialize the database tag \fItbl\fP
  1704. before any data are entered or retrieved from that tree.
  1705. It assumes that the tag has not been used
  1706. to store a tree, and therefore does not attempt to free any such data.
  1707. X
  1708. .TM "char *" "srtin(tbl, string, compare)" "SRTTABLE *tbl;" "char *string;" "int (*compare)();"
  1709. The existing data tree is searched for the string,
  1710. if it is found then a pointer to that string is returned.
  1711. Otherwise, space is allocated for the string and pointer structure via
  1712. \fImalloc\fP(3).
  1713. The string is copied to this new space which is linked into the tree
  1714. and a pointer to the new string is returned.
  1715. If space cannot be obtained, the operation is aborted and NULL is returned
  1716. (the data structure remains consistent, but the string is not added).
  1717. The strings are compared and sorted with the subroutine pointed to by
  1718. \fIcompare\fP.  This subroutine takes two string pointers as arguments.
  1719. It returns zero if the strings are the same,
  1720. less than zero if the first string should precede the second, and
  1721. greater than zero if the second string should precede the first.
  1722. Use \fIstrcmp\fP(3) if simple lexicographical ordering is desired.
  1723. It is confusing at best if different \fIcompare\fP functions are used
  1724. when inserting strings into a given tree.
  1725. X
  1726. .TM "char *" "srtmem(tbl, string, compare)" "SRTTABLE *tbl;" "char *string;" "int (*compare)();"
  1727. Return the database entry for \fIstring\fP if it is already a member of
  1728. the table, else NULL.
  1729. X
  1730. .TM "int" "srtdel(tbl, string, compare)" "SRTTABLE *tbl;" "char *string;" "int (*compare)();"
  1731. The existing data tree is searched for the string,
  1732. if it is found then it is deleted and a nonzero value is returned.
  1733. Otherwise, 0 is returned.
  1734. X
  1735. .TM "void" "srtgti(tbl);" "SRTTABLE *tbl;"
  1736. This subroutine initializes the database tag pointed to by \fItbl\fP
  1737. so that a tree traversal can be made via \fIsrtgets\fP.
  1738. X
  1739. .TM "char *" "srtgets(tbl);" "SRTTABLE *tbl;"
  1740. This subroutine extracts the next string from the data structure.
  1741. The strings are returned in the order specified by the \fIcompare\fP
  1742. function when they were inserted with \fIsrtin\fP.
  1743. When the list is exhausted, NULL is returned.
  1744. X
  1745. .TM "int" "srtapply(tbl, func)" "SRTTABLE *tbl;" "int (*func)();"
  1746. This subroutine applies the \fIfunc\fP to each string in the tree (order
  1747. determined by \fIcompare\fP when they were inserted) until the func returns
  1748. non-zero, or there are no more strings.  If the \fIfunc\fP returned
  1749. non-zero then that value is returned, otherwise 0 is returned.
  1750. X
  1751. .TM "void" "srtfree(tbl)" "SRTTABLE *tbl;"
  1752. This subroutine deletes a database, and re-initializes the
  1753. database tag.
  1754. It assumes that the database tag was initialized at one time via \fIsrtinit\fP
  1755. (other routines will probably also have been called).
  1756. The space formally occupied by string data and pointer structures is
  1757. deallocated via \fIfree\fP(3).
  1758. X
  1759. .TM "void" "srtdtree(tbl, ent)" "SRTTABLE *tbl;" "SRTENTRY *ent;"
  1760. This subroutine recursively deletes a database subtree.
  1761. The space formally occupied by the string data and pointer structures is
  1762. deallocated via \fIfree\fP(3).
  1763. This routine is most likely only of use internally.
  1764. .SH EXAMPLE
  1765. .nf
  1766. #include <stdio.h>
  1767. main()
  1768. {
  1769. X    extern int strcmp();
  1770. X    SRTTABLE tree;
  1771. X    char buf[80], *p;
  1772. X    int i;
  1773. X
  1774. X    /* init the tree */
  1775. X    srtinit(&tree);
  1776. X
  1777. X    /* add some strings */
  1778. X    while (NULL != fgets(buf, 80, stdin))  /* want the \en terminator */
  1779. X        if (NULL == (p = srtin(&tree, buf, strcmp)))
  1780. X            printf("out of memory!\en");
  1781. X    
  1782. X    /* init tree for srtgets */
  1783. X    srtgti(&tree);
  1784. X
  1785. X    /* print out the strings with srtapply and printf -- can't have
  1786. X     * a legal printf % escape in the strings! */
  1787. X    (void) srtapply(&tree, printf);
  1788. X
  1789. X    /* use srtgets to print the strings out this time -- keep count */
  1790. X    for (i = 0; NULL != (p = srtgets(&tree)); ++i)
  1791. X        printf("string %2d is: %s\en", i, p);
  1792. X    printf("there were %d strings\en", i);
  1793. X
  1794. X    /* free the database */
  1795. X    srtfree(&tree);
  1796. }
  1797. .fi
  1798. .SH DIAGNOSTICS
  1799. There are no messages printed by these routines.
  1800. Catchable errors are returned as NULL.
  1801. Compiled in errors such as the use of strings that
  1802. are not null terminated tend to result in core files.
  1803. .SH FILES
  1804. /usr/local/lib/libsrtunq.a
  1805. .br
  1806. /usr/include/local/srtunq.h
  1807. .SH SEE ALSO
  1808. malloc(3), free(3), qsort(3), strcmp(3)
  1809. .SH AUTHOR
  1810. Stephen Uitti, PUCC
  1811. .SH BUGS
  1812. The structure names and typedefs seem confused.  The typedefs make more sense.
  1813. Purdue
  1814. chmod 0444 libsrtunq/libsrtunq.3l ||
  1815. echo 'restore of libsrtunq/libsrtunq.3l failed'
  1816. Wc_c="`wc -c < 'libsrtunq/libsrtunq.3l'`"
  1817. test 5705 -eq "$Wc_c" ||
  1818.     echo 'libsrtunq/libsrtunq.3l: original size 5705, current size' "$Wc_c"
  1819. fi
  1820. # ============= maketd/abrv.c ==============
  1821. if test -f 'maketd/abrv.c' -a X"$1" != X"-c"; then
  1822.     echo 'x - skipping maketd/abrv.c (File already exists)'
  1823. else
  1824. echo 'x - extracting maketd/abrv.c (Text)'
  1825. sed 's/^X//' << 'Purdue' > 'maketd/abrv.c' &&
  1826. /*
  1827. X * abbreviation related routines 
  1828. X * Written & hacked by Stephen Uitti, PUCC staff
  1829. X * 1985 maketd is copyright (C) Purdue University, 1985 
  1830. X *
  1831. X * Permission is hereby given for its free reproduction and modification for
  1832. X * non-commercial purposes, provided that this notice and all embedded
  1833. X * copyright notices be retained. Commercial organizations may give away
  1834. X * copies as part of their systems provided that they do so without charge,
  1835. X * and that they acknowledge the source of the software. 
  1836. X */
  1837. X
  1838. #include "machine.h"
  1839. X
  1840. #ifdef pdp11
  1841. #include <sys/types.h>
  1842. #endif
  1843. #include <stdio.h>
  1844. #include <ctype.h>
  1845. X
  1846. extern char *strrchr();
  1847. X
  1848. #include "srtunq.h"
  1849. #include "abrv.h"
  1850. #include "main.h"
  1851. #include "maketd.h"
  1852. #include "errors.h"
  1853. X
  1854. #define SPACE    '\040'        /* ascii for space            */
  1855. X
  1856. struct srtent abrv;        /* include file abrevs            */
  1857. char   *abrvtbl[MXABR];        /* translation table strings        */
  1858. int     abrvlen[MXABR];        /* string lengths (for speed)        */
  1859. X
  1860. /*
  1861. X * lngsrt - string length more important than lexicographical compare. 
  1862. X * return > 0 if b is longer than a. 
  1863. X * return < 0 if b is shorter than a. 
  1864. X * if a & b are * the same length, return strcmp(a, b), which means that 
  1865. X * 0 is returned if the strings are THE SAME, 
  1866. X * if b > a: return > 0 if b < a: return < 0 
  1867. X */
  1868. int
  1869. lngsrt(a, b)
  1870. char   *a, *b;
  1871. {
  1872. X    register int i;
  1873. X
  1874. X    if (0 != (i = strlen(b) - strlen(a)))
  1875. X        return i;
  1876. X    return strcmp(a, b);
  1877. }
  1878. X
  1879. /*
  1880. X * hincl - include header optimizer: 
  1881. X * Compress multiple leading /'s to just one. Remove leading "./". 
  1882. X * Doesn't change date, just returns pointer into beginning of path. 
  1883. X */
  1884. char *
  1885. hincl(p)
  1886. register char *p;
  1887. {
  1888. X    if ('/' == *p) {        /* compress multiple leading /'s */
  1889. X        while ('/' == p[1])    /* to just one */
  1890. X            ++p;
  1891. X    }
  1892. X    if (0 == strncmp("./", p, 2)) {
  1893. X        p += 2;            /* leading "./" can confuse make */
  1894. X        while ('/' == *p)    /* don't change ".//a.h" to "/a.h" */
  1895. X            ++p;
  1896. X    }
  1897. X    return p;
  1898. }
  1899. X
  1900. /* makeabrv
  1901. X * add an abreviation to the table
  1902. X */
  1903. void
  1904. makeabrv(pos, p)
  1905. int pos;
  1906. char *p;
  1907. {
  1908. X    register int len;
  1909. X
  1910. X    if (NULL != abrvtbl[pos]) {
  1911. X        fprintf(stderr, "%s: macro letter '%c' redefined\n", progname, 'A' + pos);
  1912. X        return;
  1913. X    }
  1914. X    abrvtbl[pos] = p;
  1915. X    if (3 > (len = strlen(p))) {    /* don't use, but hold letter    */
  1916. X        len = 0;
  1917. X    }
  1918. X    abrvlen[pos] = len;
  1919. X    if (FALSE != verbose) {
  1920. X        fprintf(stderr, "%s: %c='%s'\n", progname, pos + 'A', p);
  1921. X    }
  1922. }
  1923. X
  1924. /*
  1925. X * srchincl - search line for make defines of A-Z Put entries into abrvtbl. 
  1926. X */
  1927. void
  1928. srchincl(p)
  1929. register char *p;
  1930. {
  1931. X    register char letter, *q, *r;
  1932. X    register unsigned i;
  1933. X    extern char *malloc();
  1934. X
  1935. X    if (FALSE == shortincl || '\000' == *p) {
  1936. X        return;
  1937. X    }
  1938. X
  1939. X    while (isspace(*p))        /* ignore white space */
  1940. X        ++p;
  1941. X    letter = *p++;
  1942. X    if (! isupper(letter)) {
  1943. X        return;
  1944. X    }
  1945. X
  1946. X    while (isspace(*p))
  1947. X        ++p;
  1948. X    if ('=' != *p++) {
  1949. X        return;
  1950. X    }
  1951. X
  1952. X    while (isspace(*p))
  1953. X        ++p;
  1954. X    i = strlen(p);
  1955. X
  1956. X    if (NULL == (q = r = malloc(i+1))) {
  1957. X        OutOfMemory();
  1958. X    }
  1959. X
  1960. X    while ('\000' != *p && '#' != *p && ! isspace(*p))
  1961. X        *q++ = *p++;
  1962. X    *q = '\000';
  1963. X
  1964. X    makeabrv(letter-'A', r);
  1965. X    if (FALSE != verbose)
  1966. X        fprintf(stderr, "%s: use macro %c as %s\n", progname, letter, r);
  1967. }
  1968. X
  1969. /*
  1970. X * abrvsetup - set up abrev table, spit out the abrevs.     
  1971. X * Use any A-Z definitions found in Makefile, no duplicates.  
  1972. X * look at each sting we have noticed as a prefix
  1973. X *  (make sure is non-NULL, not too small)
  1974. X * macro them
  1975. X * output table
  1976. X */
  1977. void
  1978. abrvsetup()
  1979. {
  1980. X    register int i;            /* scan tables            */
  1981. X    register char *p;        /* surrent abrev. canidate    */
  1982. X    register char *q;        /* temp string            */
  1983. X    register int slot;        /* slot search point        */
  1984. X
  1985. X    srtgti(&abrv);
  1986. X    while (NULL != (p = srtgets(&abrv))) {
  1987. X        if (FALSE != verbose)
  1988. X            fprintf(stderr, "%s: examine %s, ", progname, p);
  1989. X        slot = -1;
  1990. X        for (i = 0; i < MXABR; ++i) {
  1991. X            q = abrvtbl[i];
  1992. X            if (NULL == q) {
  1993. X                if (slot == -1)
  1994. X                    slot = i;
  1995. X                continue;
  1996. X            }
  1997. X            if (0 == strcmp(p, q))
  1998. X                break;
  1999. X        }
  2000. X
  2001. X        /* already in table or no more room in table
  2002. X         */
  2003. X        if (MXABR != i || slot == -1) {
  2004. X            if (FALSE != verbose)
  2005. X                fprintf(stderr, "rejected\n");
  2006. X            continue;
  2007. X        }
  2008. X
  2009. X        /* slot is a known free slot,
  2010. X         * but we'd rather be mnemonic
  2011. X         */
  2012. X        q = strrchr(p, '/');
  2013. X        if ((char *)0 != q && isalpha(q[1])) {
  2014. X            i = q[1] - (islower(q[1]) ? 'a' : 'A');
  2015. X            if (NULL == abrvtbl[i])
  2016. X                slot = i;
  2017. X        }
  2018. X        if (FALSE != verbose)
  2019. X            fprintf(stderr, "accepted as %c\n", slot+'A');
  2020. X        makeabrv(slot, p);
  2021. X        fprintf(makefp, "%c=%s\n", slot+'A', p);
  2022. X    }
  2023. }
  2024. X
  2025. /*
  2026. X * findabr - find an abbreviation in abrvtbl for string p (if any). 
  2027. X * if multiple abbreations work, use longest. (ie: /usr/include &
  2028. X * /usr/include/sys; use /usr/include/sys) if found, return index else: MXABR
  2029. X */
  2030. int
  2031. findabr(p)
  2032. register char *p;        /* string pointer            */
  2033. {
  2034. X    register int i;        /* for index                */
  2035. X    register int j;        /* found index                */
  2036. X
  2037. X    for (i = 0, j = MXABR; i < MXABR; ++i) {
  2038. X        if (0 == abrvlen[i])
  2039. X            continue;
  2040. X        if (0 == strncmp(abrvtbl[i], p, abrvlen[i]))
  2041. X            if (MXABR == j || abrvlen[i] > abrvlen[j])
  2042. X                j = i;
  2043. X    }
  2044. X    return j;
  2045. }
  2046. Purdue
  2047. chmod 0444 maketd/abrv.c ||
  2048. echo 'restore of maketd/abrv.c failed'
  2049. Wc_c="`wc -c < 'maketd/abrv.c'`"
  2050. test 4905 -eq "$Wc_c" ||
  2051.     echo 'maketd/abrv.c: original size 4905, current size' "$Wc_c"
  2052. fi
  2053. # ============= libopt/envopt.c ==============
  2054. if test -f 'libopt/envopt.c' -a X"$1" != X"-c"; then
  2055.     echo 'x - skipping libopt/envopt.c (File already exists)'
  2056. else
  2057. echo 'x - extracting libopt/envopt.c (Text)'
  2058. sed 's/^X//' << 'Purdue' > 'libopt/envopt.c' &&
  2059. /*
  2060. X * take options from an envirionment variable
  2061. X */
  2062. #include <stdio.h>
  2063. #include "getopt.h"
  2064. X
  2065. extern char **_eargv;
  2066. extern int _eargc;
  2067. X
  2068. /* breakargs - break a string into a string vector for execv.
  2069. X * Note, when done with the vector, mearly "free" the vector.
  2070. X * Written by Stephen Uitti, PUCC, Nov '85 for the new version
  2071. X * of "popen" - "nshpopen", that doesn't use a shell.
  2072. X * (used here for the as filters, a newer option).
  2073. X *
  2074. X * breakargs is copyright (C) Purdue University, 1985
  2075. X *
  2076. X * put in a fix for cmds lines with "string string" in them
  2077. X * Mon Aug 25 13:34:27 EST 1986 (ksb)
  2078. X *
  2079. X * Permission is hereby given for its free reproduction and
  2080. X * modification for non-commercial purposes, provided that this
  2081. X * notice and all embedded copyright notices be retained.
  2082. X * Commercial organisations may give away copies as part of their
  2083. X * systems provided that they do so without charge, and that they
  2084. X * acknowledge the source of the software.
  2085. X */
  2086. #ifdef BSD2_9
  2087. #include <sys/types.h>
  2088. #endif
  2089. #include <stdio.h>            /* for nothing, really */
  2090. #define SPC '\040'            /* ascii space */
  2091. X
  2092. char *
  2093. mynext(pch)
  2094. register char *pch;
  2095. {
  2096. X    register int fQuote;
  2097. X
  2098. X    for (fQuote = 0; (*pch != '\000' && *pch != SPC && *pch != '\t')||fQuote; ++pch) {
  2099. X        if ('\\' == *pch) {
  2100. X            continue;
  2101. X        }
  2102. X        switch (fQuote) {
  2103. X        default:
  2104. X        case 0:
  2105. X            if ('"' == *pch) {
  2106. X                fQuote = 1;
  2107. X            } else if ('\'' == *pch) {
  2108. X                fQuote = 2;
  2109. X            }
  2110. X            break;
  2111. X        case 1:
  2112. X            if ('"' == *pch)
  2113. X                fQuote = 0;
  2114. X            break;
  2115. X        case 2:
  2116. X            if ('\'' == *pch)
  2117. X                fQuote = 0;
  2118. X            break;
  2119. X        }
  2120. X    }
  2121. X    return pch;
  2122. }
  2123. X
  2124. /*
  2125. X * given an envirionment variable insert it in the option list (exploded)
  2126. X */
  2127. int
  2128. envopt(cmd)
  2129. char *cmd;
  2130. {
  2131. X    register char *p;        /* tmp                */
  2132. X    register char **v;        /* vector of commands returned    */
  2133. X    register unsigned sum;        /* bytes for malloc        */
  2134. X    register int i;            /* number of args        */
  2135. X    register char *s;        /* save old position        */
  2136. X    register char hold;        /* hold a character for a second*/
  2137. X    extern char *malloc(), *strcpy();
  2138. X
  2139. X    p = cmd;
  2140. X    while (*p == SPC || *p == '\t')
  2141. X        p++;
  2142. X    cmd = p;            /* no leading spaces        */
  2143. X    sum = sizeof(char *);
  2144. X    i = 1;
  2145. X    while (*p != '\0') {        /* space for argv[];        */
  2146. X        ++i;
  2147. X        s = p;
  2148. X        p = mynext(p);
  2149. X        sum += sizeof(char *) + 1 + (unsigned)(p - s);
  2150. X        while (*p == SPC || *p == '\t')
  2151. X            p++;
  2152. X    }
  2153. X    ++i;
  2154. X    /* vector starts at v, copy of string follows NULL pointer */
  2155. X    v = (char **)malloc(sum+sizeof(char *));
  2156. X    if (v == NULL)
  2157. X        return 0;
  2158. X    p = (char *)v + i * sizeof(char *); /* after NULL pointer */
  2159. X    i = 0;                /* word count, vector index */
  2160. X    v[i++] = "";
  2161. X    while (*cmd != '\0') {
  2162. X        v[i++] = p;
  2163. X        s = cmd;
  2164. X        cmd = mynext(cmd);
  2165. X        hold = *cmd;
  2166. X        *cmd = '\000';
  2167. X        strcpy(p, s);
  2168. X        p += strlen(p);
  2169. X        ++p;
  2170. X        if ('\000' != hold)
  2171. X            *cmd++ = hold;
  2172. X        while (*cmd == SPC || *cmd == '\t')
  2173. X            ++cmd;
  2174. X    }
  2175. X    v[i] = (char *)NULL;
  2176. X    _eargv = v;
  2177. X    _eargc = i;
  2178. X    return i;
  2179. }
  2180. Purdue
  2181. chmod 0444 libopt/envopt.c ||
  2182. echo 'restore of libopt/envopt.c failed'
  2183. Wc_c="`wc -c < 'libopt/envopt.c'`"
  2184. test 2814 -eq "$Wc_c" ||
  2185.     echo 'libopt/envopt.c: original size 2814, current size' "$Wc_c"
  2186. fi
  2187. true || echo 'restore of maketd/main.c failed'
  2188. echo End of part 1, continue with part 2
  2189. exit 0
  2190.  
  2191. exit 0 # Just in case...
  2192.