home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / net / LaTex.index.1 < prev    next >
Internet Message Format  |  1986-06-01  |  45KB

  1. From simpson@trwrb.UUCP (Scott Simpson) Fri May 30 20:17:09 1986
  2. Path: seismo!lll-crg!styx!nike!cad!ucbvax!sdcsvax!sdcrdcf!trwrb!simpson
  3. From: simpson@trwrb.UUCP (Scott Simpson)
  4. Newsgroups: net.sources
  5. Subject: LaTeX Index Processor (Part 1)
  6. Message-ID: <1109@trwrb.UUCP>
  7. Date: 31 May 86 00:17:09 GMT
  8. Organization: TRW EDS, Redondo Beach, CA
  9. Lines: 1644
  10. Keywords: LaTeX, Index Processor
  11.  
  12. Here is an index processor for converting LaTeX ".idx" files to "theindex"
  13. environments.  The second part contains a set of libraries it uses.
  14. I have only tested the program on a Pyramid 98x running 4.2 BSD although
  15. it should port to VAXen readily.  If you are not running on a Pyramid,
  16. you'll want to remove the routine "getunent" from the "trw" library
  17. since universes don't make sense.
  18. -------------------------------------------------------------------------
  19. #! /bin/sh
  20. # To extract, remove mail header lines and type "sh filename"
  21. echo x - Makefile
  22. sed -e 's/^X//' > Makefile << '!FaR!OuT!'
  23. XDEST=/usr/local/bin
  24. XLFLAGS=
  25. XYFLAGS=
  26. XLDFLAGS=-s
  27. XCFLAGS=-O
  28. XLOADLIBES=-ltrw -lprofile -lglob -ll
  29. X
  30. Xall: index
  31. X
  32. Xindex: indexlex.c index.o
  33. X    $(CC) $(CFLAGS) $(LDFLAGS) -o index index.o $(LOADLIBES)
  34. X
  35. Xindexlex.c: indexlex.l
  36. X
  37. Xindex.o: indexlex.c
  38. X
  39. Xinstall: all
  40. X    install index $(DEST)
  41. X
  42. Xclean:
  43. X    -rm *.o lex.yy.c y.tab.c indexlex.c index
  44. !FaR!OuT!
  45. echo x - index.1
  46. sed -e 's/^X//' > index.1 << '!FaR!OuT!'
  47. X.if t .ds LX L\v'-.22m'a\v'.22m'T\h'-.1667m'\v'.22m'E\h'-.125m'\v'-.22m'X
  48. X.if n .ds LX LaTeX
  49. X.TH INDEX 1 TRW
  50. X.UC
  51. X.SH NAME
  52. Xindex \- index processor for converting LaTeX idx files
  53. X.SH ORIGIN
  54. XTRW
  55. X.SH SYNOPSIS
  56. X.B index [ -l ]
  57. X.B [ -f
  58. X.I alphabetizefile
  59. X.B ] [
  60. X.I file...
  61. X.B ]
  62. X.SH DESCRIPTION
  63. X.I Index
  64. Xconverts 
  65. X.I idx 
  66. Xfiles generated by \*(LX into 
  67. X.I theindex 
  68. Xenvironments that can be processed by \*(LX.
  69. XMultiple files may be given.
  70. XIf the file is not found, the extension
  71. X.I idx
  72. Xis appended and the new file is looked for.
  73. XIndex files will be created with the extension
  74. X.I ind.
  75. XIf no files are given, standard input is read and standard output it written.
  76. XSubitems and subsubitems can be generated by separating index entries
  77. Xwith commas.
  78. XFor example, after running your document
  79. Xthrough \*(LX you may obtain an index file 
  80. X.I sample.idx
  81. Xcontaining entries
  82. Xthat look like
  83. X.RS
  84. X.nf
  85. X\eindexentry{Reagan}{32}
  86. X\eindexentry{Reagan}{54}
  87. X\eindexentry{Reagan,republicans}{54}
  88. X\eindexentry{Carter}{60}
  89. X\eindexentry{Reagan,republicans,conventions}{62}
  90. X.fi
  91. X.RE
  92. XAfter running the index file through
  93. X.I index
  94. Xa file
  95. X.I sample.ind 
  96. Xwill be created that will contain
  97. X.RS
  98. X.nf
  99. X\ebegin{theindex}
  100. X\eitem Carter 60
  101. X\eindexspace 
  102. X\eitem Reagan 32, 54
  103. X  \esubitem republicans 54
  104. X    \esubsubitem conventions 62
  105. X\eend{theindex}
  106. X.fi
  107. X.RE
  108. XThe 
  109. X.I indexspace 
  110. Xleaves a little extra vertical space between the entries that start with
  111. Xa new letter.
  112. XIf the 
  113. X.I -l 
  114. Xoption is given, then a large index letter will precede each entry
  115. Xthat starts with a new letter.
  116. X.PP
  117. X.I Index
  118. Xreads the file
  119. X.I .alphabetize
  120. Xin the home directory if it exists
  121. Xto determine how to alphabetize an
  122. X.I idx
  123. Xfile.
  124. XThis file contains rules for skipping control sequences, characters, etc
  125. Xwhen alphabetizing a file.
  126. XThe format of this file is described in
  127. X.IR index (5).
  128. XIf the 
  129. X.I -f 
  130. Xoption is given, then another alphabetization file can be given.
  131. X.PP
  132. XA dash following an entry indicates the beginning of a range. 
  133. XThe range is ended by the occurence of the next equivalent entry.
  134. XFor example, suppose you had a \*(LX file containing
  135. X.RS
  136. X.nf
  137. X\&...and they fought\eindex{fighting-} and wept...
  138. X.fi
  139. X.RE
  140. Xon page 40 and
  141. X.RS
  142. X.nf
  143. X\&...and were still fighting\eindex{fighting} years later...
  144. X.fi
  145. X.RE 
  146. Xon page 42 with no intervening
  147. X.I \eindex
  148. Xcommands.
  149. XThen after running the 
  150. X.I idx
  151. Xfile through 
  152. X.I index,
  153. Xthe line 
  154. X.RS
  155. X.nf
  156. X\eitem fighting 40--42
  157. X.fi
  158. X.RE 
  159. Xwould be contained in the 
  160. X.I ind 
  161. Xfile.
  162. XWhen ranges are given for subitems and subsubitems, only the last
  163. Xcomma separated entry should have a dash suffix.
  164. XDuplicate page numbers are suppressed.
  165. X.PP
  166. XIf you wish to insert a comma into your index entry, you will need to 
  167. Xhide it from the index processor with braces
  168. Xsince only outer level commas are recognized as item delimeters.
  169. XFor example,
  170. X.RS
  171. X.nf
  172. X\eindex{Reagan{,} Ronald}
  173. X.fi
  174. X.RE
  175. Xgenerates the index entry for
  176. X.I Reagan, Ronald.
  177. X.SH FILES
  178. X.nf
  179. X.ta \w'~/.alphabetize  'u
  180. X~/.alphabetize    Default alphabetization file
  181. X.fi
  182. X.SH AUTHOR
  183. XScott Simpson
  184. X.SH SEE ALSO
  185. Xprofile(3), index(5), profile(5)
  186. X.SH DIAGNOSTICS
  187. XComplains about illegal values in bindings in alphabetization file.
  188. !FaR!OuT!
  189. echo x - index.5
  190. sed -e 's/^X//' > index.5 << '!FaR!OuT!'
  191. X.if t .ds LX L\v'-.22m'a\v'.22m'T\h'-.1667m'\v'.22m'E\h'-.125m'\v'-.22m'X
  192. X.if n .ds LX LaTeX
  193. X.TH INDEX 5 TRW
  194. X.UC
  195. X.SH NAME
  196. Xindex \- format of alphabetization stanza for LaTeX index processor
  197. X.SH ORIGIN
  198. XTRW
  199. X.SH SYNOPSIS
  200. X~/.alphabetize
  201. X.SH DESCRIPTION
  202. XThe \*(LX index processor
  203. X.IR index (1)
  204. Xreads the file
  205. X.I .alphabetize
  206. Xfile in the home directory to determine
  207. Xhow to sort index entries.
  208. XThis file is in 
  209. X.IR profile (5)
  210. Xformat and consists of a stanza containing bindings.
  211. XThese bindings consist of key/value pairs.
  212. XThere may be multiple values for each key.
  213. X.PP
  214. XThe stanza contained in the 
  215. X.I .alphabetize 
  216. Xfile should contain one stanza with the marker 
  217. X.I alphabetize.
  218. XThis stanza may contain three keys: 
  219. X.I skipchars,
  220. X.I mapctrlsequence 
  221. Xand 
  222. X.I mapindexentry.
  223. X.PP
  224. X.I Skipchars
  225. Xis a list of characters to ignore when alphabetizing index entries.
  226. X.PP
  227. X.I Mapctrlsequence
  228. Xis a list of pairs of values.
  229. XThe odd numbered value 
  230. X.I n
  231. X(a control sequence)
  232. Xmaps into the even value
  233. X.I n+1
  234. X(any text).
  235. XThe leading backslash may 
  236. Xbe omitted for the odd control sequence strings.
  237. X.PP
  238. X.I Mapindexentry
  239. Xis a list of index entries to match exactly.
  240. XThe odd numbered value
  241. X.I n
  242. X(an index entry) maps into the even value
  243. X.I n+1
  244. X(any text).
  245. XThe backslashes
  246. Xmay not be omitted here.
  247. X.SH EXAMPLES
  248. XHere is an example stanza to help clarify some ideas.
  249. X.RS
  250. X.nf
  251. X.ta \w'    mapctrlsequence     'u
  252. Xalphabetize
  253. X{
  254. X    skipchars        '{' '}' '$' '\e^' '\e'' '`' '_' '"'
  255. X    mapctrlsequence    "\e\etrwlogo" "TRW" \e
  256. X            "LaTeX" "LaTeX"
  257. X    mapindexentry    "\e\everb|\e\e\e\e|" "\e\e" \e
  258. X            "\e\everb|\e\e\e"|" "\e""
  259. X}
  260. X.fi
  261. X.RE
  262. XWhen alphabetizing the index file, the characters {, }, $, ^, ', `, _,
  263. Xand " will be ignored.
  264. X.IR Profile (5)
  265. Xrequires escaping the ^, ' and \e.
  266. X.PP
  267. XThe control word
  268. X.I \etrwlogo
  269. Xwill be treated as the string
  270. X.I TRW
  271. Xwherever it occurs in an index entry
  272. Xand the control word
  273. X.I \eLaTeX
  274. Xwill be treated as 
  275. X.I LaTeX
  276. Xwherever it occurs in an index entry.
  277. XNote that the leading backslash in the third value (i.e.,
  278. X.IR \eLaTeX )
  279. Xcan be omitted without ill effect.
  280. XNormally, control words and control symbols are removed when alphabetizing.
  281. X.PP
  282. XThe index entries
  283. X.I \everb|\e\e|
  284. Xand
  285. X\fI\everb|\e"|\fR
  286. Xwill be treated as \e and " when alphabetizing, respectively.
  287. X.PP
  288. XHere is one last example illustrating the sorting rules.
  289. XSuppose we have the stanza
  290. X.RS
  291. X.nf
  292. X.ta \w'    mapctrlsequence     'u
  293. Xalphabetize
  294. X{
  295. X    skipchars        '{' '}'
  296. X    mapctrlsequence    "\e\ehello" "salutation"
  297. X    mapindexentry    "{\e\ela de da}" "z"
  298. X}
  299. X.fi
  300. X.RE
  301. Xand we have the
  302. X.I \eindex
  303. Xcommands
  304. X.RS
  305. X.nf
  306. X\eindex{{\ebf Orca!} kills}
  307. X\eindex{say,{\ela de da}}
  308. X\eindex{say,{\ehello} there}
  309. X\eindex{say,mazzard}
  310. X\eindex{{\ela de da} de da}
  311. X\eindex{{\eit Wolfman} Jack}
  312. X.fi
  313. X.RE
  314. Xsprinkled throughout the document.
  315. X\*(LX may generate the following 
  316. X.I idx
  317. Xfile
  318. X.RS
  319. X.nf
  320. X\eindexentry{{\ebf Orca!} kills}{5}
  321. X\eindexentry{say,{\ela de da}}{10}
  322. X\eindexentry{say,{\ehello} there}{15}
  323. X\eindexentry{say,mazzard}{20}
  324. X\eindexentry{{\ela de da} de da}{25}
  325. X\eindexentry{{\eit Wolfman} Jack}{30}
  326. X.fi
  327. X.RE
  328. XAfter running through
  329. X.I index
  330. Xwe obtain the 
  331. X.I ind
  332. Xfile
  333. X.RS
  334. X.nf
  335. X\ebegin{theindex}
  336. X\eitem {\ela de da} de da 25
  337. X\eindexspace
  338. X\eitem {\ebf Orca!} kills 5
  339. X\eindexspace
  340. X\eitem say
  341. X  \esubitem mazzard 20
  342. X  \esubitem {\ehello} there 15
  343. X  \esubitem {\ela de da} 10
  344. X\eindexspace
  345. X\eitem {\eit Wolfman} Jack 30
  346. X\eend{theindex}
  347. X.fi
  348. X.RE
  349. XThe entries are logically sorted using the strings
  350. X.RS
  351. X.nf
  352. Xdedadeda
  353. XOrca!kills
  354. Xsay
  355. X  mazzard
  356. X  salutationthere
  357. X  z
  358. XWolfmanJack
  359. X.fi
  360. X.RE
  361. XNote that the 
  362. X.I mapindexentry
  363. Xmust match everything between the commas and braces while the 
  364. X.I mapctrlsequence
  365. Xmatches control sequences anywhere within the index entry.
  366. X.SH COMMENTS
  367. XThe 
  368. X.I mapindexentry 
  369. Xentries are examined first and must completely match an index entry.
  370. XIf they match, no other alphabetizing substitution takes place.
  371. X.br
  372. XUpper and lower case letters are equivalent when sorting.
  373. XUpper case alphabetics are converted to lower case; consequently,
  374. Xmost non-alphabetic characters precede the alphabetic characters
  375. Xin the ASCII collating sequence.
  376. XThe exception are the characters {, |, } and ~.
  377. X.br
  378. XBlanks are ignored when sorting.
  379. X.br
  380. XAfter control sequences are expanded into their logical sort string,
  381. Xthey are not scanned for
  382. X.I skipchars.
  383. X.SH FILES
  384. X.nf
  385. X.ta \w'~/.alphabetize   'u
  386. X~/.alphabetize    alphabetization file
  387. X.fi
  388. X.SH AUTHOR
  389. XScott Simpson
  390. X.SH SEE ALSO
  391. Xindex(1), profile(3), profile(5), ascii(7)
  392. X.SH BUGS
  393. XThis manual page is confusing.
  394. !FaR!OuT!
  395. echo x - index.y
  396. sed -e 's/^X//' > index.y << '!FaR!OuT!'
  397. X/* Yacc parser for LaTeX index processor */
  398. X%{
  399. X#include <stdio.h>
  400. X#include <local/standard.h>
  401. X#include <local/profile.h>
  402. X#include <ctype.h>
  403. X#include <pwd.h>
  404. X#define TABLEINCREMENT    50        /* Number of additional entries added when expanding a table */
  405. X#define eq(s,t)        (!strcmp((s),(t)))
  406. X#define odd(i)        (((i) % 2) == 1)
  407. X#define ITEMDEPTH    3        /* Number of nestings of \item's, \subitem's, \subsubitem's, etc. */
  408. Xchar *ItemRep[] = { "\\item", "\\subitem", "\\subsubitem", NULL }; /* and their representation */
  409. Xchar    *calloc(), *realloc();
  410. Xenum TokenType    {controlword, controlsymbol, string, integer, comma, obrace, cbrace, whitespace};
  411. Xstruct IndexEntry {
  412. X    char        literal[81];    /* Literal representation of index entry */
  413. X    char        alphabetic[81];    /* Alphabetic representation for sorting of index entry */
  414. X    struct Token    *tokenlist;    /* Doubly linked token list */
  415. X    struct IndexEntry    *subitem;    /* Pointer to subitem table, subsubitem table, etc */
  416. X    int            subitemcount;    /* Number of items in subitem table */
  417. X    int            subitemtabsize;    /* Subitem table size currently allocated */
  418. X    struct PageNoTable    *pagenos;    /* List of page numbers */
  419. X    int            pagetablecount;    /* Number of items in page number table */
  420. X    int            pagetablesize;    /* Size of page number table currently allocated */
  421. X};
  422. Xstruct Token {
  423. X    enum TokenType    type;        /* Token type */
  424. X    char        lexeme[81];    /* Representation of all the token types */
  425. X    struct Token    *prev, *next;
  426. X};
  427. Xstruct PageNoTable {
  428. X    int            number;        /* Page number */
  429. X    Boolean        range;        /* True if this is the beginning of a range */
  430. X};
  431. Xstruct IndexEntry    *IndexTable = NULL;    /* Table of primary index entries */
  432. Xint            IndexTableCount = 0;    /* Count of number of elements used in index table */
  433. Xint            IndexTableSize = 0;    /* Current allocated size of index table */
  434. Xint            ExitStatus = SUCCEED;    /* Guess */
  435. Xint            LineNo = 1;        /* Line number at start of token */
  436. Xint            EndLineNo = 1;        /* Line number at end of token */
  437. XBoolean            Label = FALSE;        /* True if -l option given */
  438. XBoolean            Range;            /* True if this \indexentry is a range */
  439. XPROFILE_STANZA        *SortStanza = NULL;    /* Alphabetize stanza */
  440. Xextern int        optind;            /* From getopt(3) */
  441. Xextern char        *optarg;
  442. Xchar            *Whoami;        /* argv[0] */
  443. Xchar            *Usage = "Usage: %s [-l] [-f alphabetizefile] [file...]\n";
  444. Xchar            *Marker[] = { "alphabetize", NULL };    /* Markers for alphabetize stanza */
  445. Xchar            IdxFileName[81];    /* .idx file name */
  446. Xchar            Literal[81];        /* Literal string of key */
  447. Xchar            Alphabetic[81];        /* Alphabetic string of key */
  448. XFILE            *InputFile;        /* Current input file */
  449. XFILE            *OutputFile;        /* Current output file */
  450. Xstruct Token        *CurKey;        /* Current key we are constructing */
  451. Xstruct IndexEntry    **CurSearchTable;    /* Current table to search for match */
  452. Xstruct IndexEntry    *CurEntry;        /* Current table entry */
  453. Xstruct IndexEntry    *PrevEntry;        /* Previous Entry */
  454. X%}
  455. X%union {
  456. X    char        value[81];
  457. X    struct Token    *t;
  458. X}
  459. X%token <value> CONTROLSEQUENCE INTEGER WHITESPACE STRING INDEXENTRY
  460. X%type <t> noncommaelement anyelement anyelements
  461. X%%
  462. Xindexfile :
  463. X    optwhitespace
  464. X    indexentries
  465. X    {
  466. X        sort(IndexTable, IndexTableCount);
  467. X        fprintf(OutputFile, "\\begin{theindex}\n");
  468. X        if (Label) {
  469. X        fprintf(OutputFile, "\\newcommand{\\largeletter}[1]{{\\huge\\hspace{-.5in}\\parbox[t]{.5in}{\\makebox[.35in][r]");
  470. X        fprintf(OutputFile, "{\\uppercase{#1}}}\\vspace{-1.5ex}}}\n");
  471. X        }
  472. X        printindexentries(IndexTable, IndexTableCount, 1);
  473. X        fprintf(OutputFile, "\\end{theindex}\n");
  474. X    }
  475. X    ;
  476. X
  477. Xindexentries :
  478. X    indexentries
  479. X    indexentry
  480. X    |
  481. X    indexentry
  482. X    ;
  483. X
  484. Xindexentry :
  485. X    INDEXENTRY
  486. X    {
  487. X        CurSearchTable = &IndexTable, PrevEntry = NULL;
  488. X        CurKey = NULL;
  489. X        Range = FALSE;
  490. X    }
  491. X    optwhitespace
  492. X    '{'
  493. X    keys
  494. X    '}'
  495. X    optwhitespace
  496. X    '{'
  497. X    optwhitespace
  498. X    INTEGER
  499. X    {
  500. X        struct PageNoTable    *p;
  501. X
  502. X        if (!(p = findpage(CurEntry->pagenos, CurEntry->pagetablecount, atoi($10)))) {
  503. X        if (CurEntry->pagetablecount >= CurEntry->pagetablesize) {
  504. X            if (!(CurEntry->pagenos = (struct PageNoTable *)reallocate(CurEntry->pagenos, CurEntry->pagetablesize,
  505. X            TABLEINCREMENT, sizeof(struct PageNoTable)))) {
  506. X            yyerror("memory allocation failure");
  507. X            exit(FAIL);
  508. X            }
  509. X            CurEntry->pagetablesize += TABLEINCREMENT;
  510. X        }
  511. X        CurEntry->pagenos[CurEntry->pagetablecount].number = atoi($10);
  512. X        CurEntry->pagenos[CurEntry->pagetablecount].range = Range;
  513. X        CurEntry->pagetablecount++;
  514. X        } else
  515. X        p->range = Range;
  516. X    }
  517. X    optwhitespace
  518. X    '}'
  519. X    optwhitespace
  520. X    ;
  521. X
  522. Xkeys :
  523. X    multiplekeys
  524. X    key
  525. X    {
  526. X    struct Token    *t;
  527. X
  528. X    for (t = CurKey; t->next; t = t->next)
  529. X        ;
  530. X    if (t->type == string)
  531. X        if (t->lexeme[strlen(t->lexeme) - 1] == '-') {
  532. X        t->lexeme[strlen(t->lexeme) - 1] = '\0';
  533. X        Range = TRUE;
  534. X        }
  535. X    goto installkey;
  536. X    }
  537. X    ;
  538. X
  539. Xmultiplekeys :
  540. X    multiplekeys
  541. X    key
  542. X    ','
  543. X    {
  544. X        struct Token    *t;
  545. X
  546. Xinstallkey: strcpy(Literal, literalstring(CurKey));
  547. X        strcpy(Alphabetic, alphabetizestring(CurKey, SortStanza));
  548. X        if (!*CurSearchTable) {
  549. X        if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, 0, TABLEINCREMENT,
  550. X        sizeof(struct IndexEntry)))) {
  551. X            yyerror("memory allocation failure");
  552. X            exit(FAIL);
  553. X        }
  554. X        if (!PrevEntry)
  555. X            IndexTableSize = TABLEINCREMENT;
  556. X        else
  557. X            PrevEntry->subitemtabsize = TABLEINCREMENT;
  558. X        }
  559. X        if (!(CurEntry = findentry(*CurSearchTable, PrevEntry ? PrevEntry->subitemcount : IndexTableCount, Literal))) {
  560. X        if (!PrevEntry) {
  561. X            if (IndexTableCount >= IndexTableSize) {
  562. X            if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, IndexTableSize, TABLEINCREMENT,
  563. X            sizeof(struct IndexEntry)))) {
  564. X                yyerror("memory allocation failure");
  565. X                exit(FAIL);
  566. X            }
  567. X            IndexTableSize += TABLEINCREMENT;
  568. X            }
  569. X            CurEntry = (*CurSearchTable + IndexTableCount);
  570. X            IndexTableCount++;
  571. X        } else {
  572. X            if (PrevEntry->subitemcount >= PrevEntry->subitemtabsize) {
  573. X            if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, PrevEntry->subitemtabsize,
  574. X            TABLEINCREMENT, sizeof(struct IndexEntry)))) {
  575. X                yyerror("memory allocation failure");
  576. X                exit(FAIL);
  577. X            }
  578. X            PrevEntry->subitemtabsize += TABLEINCREMENT;
  579. X            }
  580. X            CurEntry = (*CurSearchTable + PrevEntry->subitemcount);
  581. X            PrevEntry->subitemcount++;
  582. X        }
  583. X        strcpy(CurEntry->literal, Literal);
  584. X        strcpy(CurEntry->alphabetic, Alphabetic);
  585. X        CurKey->prev = CurEntry->tokenlist, CurEntry->tokenlist = CurKey;
  586. X        CurEntry->subitem = NULL, CurEntry->subitemcount = CurEntry->subitemtabsize = 0;
  587. X        CurEntry->pagenos = NULL, CurEntry->pagetablecount = CurEntry->pagetablesize = 0;
  588. X        }
  589. X        CurSearchTable = &CurEntry->subitem;
  590. X        PrevEntry = CurEntry;
  591. X        CurKey = NULL;
  592. X    }
  593. X    |
  594. X    /* epsilon */
  595. X    ;
  596. X
  597. Xkey :
  598. X    key
  599. X    noncommaelement
  600. X    |
  601. X    noncommaelement
  602. X    ;
  603. X
  604. Xnoncommaelement :
  605. X    CONTROLSEQUENCE
  606. X    {
  607. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  608. X        yyerror("memory allocation failure");
  609. X        exit(FAIL);
  610. X        }
  611. X        $$->type = isalpha($1[1]) ? controlword : controlsymbol;
  612. X        strcpy($$->lexeme, $1);
  613. X        $$->next = NULL;
  614. X        if (!CurKey)
  615. X        $$->prev = CurKey, CurKey = $$;
  616. X        else {
  617. X        struct Token *p;
  618. X        
  619. X        for (p = CurKey; p->next; p = p->next)
  620. X            ;
  621. X        p->next = $$, $$->prev = p;
  622. X        }
  623. X        $$ = CurKey;
  624. X    }
  625. X    |
  626. X    INTEGER
  627. X    {
  628. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  629. X        yyerror("memory allocation failure");
  630. X        exit(FAIL);
  631. X        }
  632. X        $$->type = integer;
  633. X        strcpy($$->lexeme, $1);
  634. X        $$->next = NULL;
  635. X        if (!CurKey)
  636. X        $$->prev = CurKey, CurKey = $$;
  637. X        else {
  638. X        struct Token *p;
  639. X        
  640. X        for (p = CurKey; p->next; p = p->next)
  641. X            ;
  642. X        p->next = $$, $$->prev = p;
  643. X        }
  644. X        $$ = CurKey;
  645. X    }
  646. X    |
  647. X    WHITESPACE
  648. X    {
  649. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  650. X        yyerror("memory allocation failure");
  651. X        exit(FAIL);
  652. X        }
  653. X        $$->type = whitespace;
  654. X        strcpy($$->lexeme, $1);
  655. X        $$->next = NULL;
  656. X        if (!CurKey)
  657. X        $$->prev = CurKey, CurKey = $$;
  658. X        else {
  659. X        struct Token *p;
  660. X        
  661. X        for (p = CurKey; p->next; p = p->next)
  662. X            ;
  663. X        p->next = $$, $$->prev = p;
  664. X        }
  665. X        $$ = CurKey;
  666. X    }
  667. X    |
  668. X    STRING
  669. X    {
  670. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  671. X        yyerror("memory allocation failure");
  672. X        exit(FAIL);
  673. X        }
  674. X        $$->type = string;
  675. X        strcpy($$->lexeme, $1);
  676. X        $$->next = NULL;
  677. X        if (!CurKey)
  678. X        $$->prev = CurKey, CurKey = $$;
  679. X        else {
  680. X        struct Token *p;
  681. X        
  682. X        for (p = CurKey; p->next; p = p->next)
  683. X            ;
  684. X        p->next = $$, $$->prev = p;
  685. X        }
  686. X        $$ = CurKey;
  687. X    }
  688. X    |
  689. X    '{'
  690. X    {
  691. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  692. X        yyerror("memory allocation failure");
  693. X        exit(FAIL);
  694. X        }
  695. X        $$->type = obrace;
  696. X        strcpy($$->lexeme, "{");
  697. X        $$->next = NULL;
  698. X        if (!CurKey)
  699. X        $$->prev = CurKey, CurKey = $$;
  700. X        else {
  701. X        struct Token *p;
  702. X
  703. X        for (p = CurKey; p->next; p = p->next)
  704. X            ;
  705. X        p->next = $$, $$->prev = p;
  706. X        }
  707. X    }
  708. X    anyelements
  709. X    '}'
  710. X    {
  711. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  712. X        yyerror("memory allocation failure");
  713. X        exit(FAIL);
  714. X        }
  715. X        $$->type = cbrace;
  716. X        strcpy($$->lexeme, "}");
  717. X        $$->next = NULL;
  718. X        if (!CurKey)
  719. X        $$->prev = CurKey, CurKey = $$;
  720. X        else {
  721. X        struct Token *p;
  722. X        
  723. X        for (p = CurKey; p->next; p = p->next)
  724. X            ;
  725. X        p->next = $$, $$->prev = p;
  726. X        }
  727. X        $$ = CurKey;
  728. X    }
  729. X    ;
  730. X
  731. Xanyelements :
  732. X    anyelements
  733. X    anyelement
  734. X    {
  735. X        $$ = $2;
  736. X    }
  737. X    |
  738. X    anyelement        /* Default action is $$ = $1 */
  739. X    ;
  740. X
  741. Xanyelement :
  742. X    noncommaelement     /* Default action is $$ = $1 */
  743. X    |
  744. X    ','
  745. X    {
  746. X        if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
  747. X        yyerror("memory allocation failure");
  748. X        exit(FAIL);
  749. X        }
  750. X        $$->type = comma;
  751. X        strcpy($$->lexeme, ",");
  752. X        $$->next = NULL;
  753. X        if (!CurKey)
  754. X        $$->prev = CurKey, CurKey = $$;
  755. X        else {
  756. X        struct Token *p;
  757. X        
  758. X        for (p = CurKey; p->next; p = p->next)
  759. X            ;
  760. X        p->next = $$, $$->prev = p;
  761. X        }
  762. X        $$ = CurKey;
  763. X    }
  764. X    ;
  765. X
  766. Xoptwhitespace :
  767. X    WHITESPACE
  768. X    |
  769. X    ;
  770. X    
  771. X%%
  772. X#include "indexlex.c"
  773. X
  774. Xmain(argc, argv)
  775. Xint    argc;
  776. Xchar    *argv[];
  777. X{
  778. X    int            c;
  779. X    Boolean        sortfilegiven = FALSE;
  780. X    char        sortfilename[81];
  781. X    char        indfilename[81];
  782. X    struct passwd    *pwentry;
  783. X    FILE        *stanzafileptr;
  784. X
  785. X    Whoami = argv[0];
  786. X    pwentry = getpwuid(geteuid());
  787. X    sprintf(sortfilename, "%s/.alphabetize", pwentry->pw_dir);
  788. X    while ((c = getopt(argc, argv, "f:l")) != EOF)
  789. X    switch (c) {
  790. X    case 'l':
  791. X        Label = TRUE;
  792. X        break;
  793. X    case 'f':
  794. X        strcpy(sortfilename, optarg);
  795. X        sortfilegiven = TRUE;
  796. X        break;
  797. X    case '?':
  798. X        fprintf(stderr, Usage, Whoami);
  799. X        exit(FAIL);
  800. X    }
  801. X    stanzafileptr = fopen(sortfilename, "r");
  802. X    if (sortfilegiven && !stanzafileptr) {
  803. X    fprintf(stderr, "%s: cannot open alphabetization file %s\n", Whoami, sortfilename);
  804. X    exit(FAIL);
  805. X    }
  806. X    if (stanzafileptr) {
  807. X    if (!(SortStanza = profile_read_profile(stanzafileptr))) {
  808. X        fprintf(stderr, "%s: file %s is not in stanza format\n", Whoami, sortfilename);
  809. X        fclose(stanzafileptr);
  810. X        exit(FAIL);
  811. X    }
  812. X    if (!(SortStanza = profile_has_stanza(SortStanza, Marker))) {
  813. X        fprintf(stderr, "%s: file %s does not contain a stanza with marker %s\n", Whoami, sortfilename, Marker[0]);
  814. X        fclose(stanzafileptr);
  815. X        exit(FAIL);
  816. X    }
  817. X    fclose(stanzafileptr);
  818. X    }
  819. X    checkstanza(SortStanza);
  820. X    if (optind == argc) {
  821. X    InputFile = stdin;
  822. X    OutputFile = stdout;
  823. X    strcpy(IdxFileName, "stdin");
  824. X    }
  825. X    do {
  826. X    if (InputFile != stdin) {
  827. X        strcpy(IdxFileName, argv[optind]);
  828. X        if (!(InputFile = fopen(argv[optind], "r"))) {
  829. X        strcpy(IdxFileName, argv[optind]);
  830. X        strcat(IdxFileName, ".idx");
  831. X        if (!(InputFile = fopen(IdxFileName, "r"))) {
  832. X            fprintf(stderr, "%s: cannot open %s\n", Whoami, IdxFileName);
  833. X            ExitStatus = FAIL;
  834. X            continue;
  835. X        }
  836. X        }
  837. X        if (strlen(IdxFileName) >= 4 && eq(&IdxFileName[strlen(IdxFileName)-4], ".idx"))
  838. X        sprintf(indfilename, "%.*s.ind", strlen(IdxFileName)-4, IdxFileName);
  839. X        else
  840. X        sprintf(indfilename, "%s.ind", IdxFileName);
  841. X        if (!(OutputFile = fopen(indfilename, "w"))) {
  842. X        fprintf(stderr, "%s: cannot open output file %s\n", Whoami, indfilename);
  843. X        fclose(InputFile);
  844. X        ExitStatus = FAIL;
  845. X        continue;
  846. X        }
  847. X    } else
  848. X        strcpy(IdxFileName, "stdin");
  849. X    if (yyparse() != 0)
  850. X        ExitStatus = FAIL;
  851. X    fclose(InputFile);
  852. X    fclose(OutputFile);
  853. X    freetables(IndexTable, IndexTableCount);
  854. X    IndexTable = NULL, IndexTableCount = IndexTableSize = 0, LineNo = EndLineNo = 1;
  855. X    yysptr = yysbuf;    /* Resets Lex lookahead buffer */
  856. X    } while (++optind < argc);
  857. X    exit(ExitStatus);
  858. X}
  859. X
  860. Xyyerror(s)
  861. Xchar *s;
  862. X{
  863. X    fprintf(stderr, "\"%s\", line %d: %s\n", IdxFileName, LineNo, s);
  864. X}
  865. X
  866. X/* Allocates additional space for tables. Returns NULL if memory allocation failure or inconsistent parameters */
  867. Xchar *reallocate(table, current, increment, elementsize)
  868. Xchar    *table;            /* pointer to current table */
  869. Xint    current;        /* current size of table */
  870. Xint    increment;        /* additional entries to add */
  871. Xint    elementsize;        /* size of an element in the table */
  872. X{
  873. X    char    *calloc(), *realloc();
  874. X    char    *p;
  875. X
  876. X    if ((!table && current > 0) || current < 0 || increment < 0 || elementsize < 0)
  877. X    return NULL;
  878. X    if (increment == 0 || elementsize == 0)
  879. X    return table;
  880. X    if (current == 0)
  881. X    if (!(p = calloc(increment, elementsize)))
  882. X        return NULL;
  883. X    else
  884. X        return p;
  885. X    else
  886. X    if (!(p = realloc(table, (current + increment) * elementsize)))
  887. X        return NULL;
  888. X    else
  889. X        return p;
  890. X}
  891. X
  892. X/* Frees the space allocated for all the tables */
  893. Xfreetables(index, noentries)
  894. Xstruct IndexEntry    *index;        /* index table */
  895. Xint            noentries;    /* number of entries in table */
  896. X{
  897. X    struct Token    *t, *ttemp;
  898. X    int            i;
  899. X
  900. X    if (!index || noentries == 0)
  901. X    return;
  902. X    for (i = 0; i < noentries; i++)
  903. X    if (index[i].subitem)
  904. X    freetables(index[i].subitem, index[i].subitemcount);    /* recursion! */
  905. X    for (t = index[i].tokenlist; t; t = ttemp)
  906. X    ttemp = t->next, free(t);
  907. X    if (index[i].pagenos)
  908. X    free(index[i].pagenos);
  909. X    free(index);
  910. X}
  911. X
  912. X/* Checks alphabetize stanza for validity */
  913. Xcheckstanza(ps)
  914. XPROFILE_STANZA    *ps;
  915. X{
  916. X    PROFILE_BINDING    *pb;
  917. X    PROFILE_VALUE    *pv;
  918. X    int            count;
  919. X
  920. X    if (!ps)
  921. X    return;
  922. X    if (pb = profile_has_binding(ps, "skipchars"))
  923. X    for (pv = pb->value; pv; pv = pv->next)
  924. X        if (pv->class != PROFILE_CHARACTER)
  925. X        switch (pv->class) {
  926. X        case PROFILE_INTEGER:
  927. X            fprintf(stderr, "%s: illegal integer constant %d in skipchars binding\n", Whoami, pv->value.i);
  928. X            break;
  929. X        case PROFILE_HEX:
  930. X            fprintf(stderr, "%s: illegal hex constant 0x%x in skipchars binding\n", Whoami, pv->value.i);
  931. X            break;
  932. X        case PROFILE_OCTAL:
  933. X            fprintf(stderr, "%s: illegal octal constant 0%o in skipchars binding\n", Whoami, pv->value.i);
  934. X            break;
  935. X        case PROFILE_FLOAT:
  936. X            fprintf(stderr, "%s: illegal float constant %f in skipchars binding\n", Whoami, pv->value.f);
  937. X            break;
  938. X        case PROFILE_STRING:
  939. X        case PROFILE_OTHER:
  940. X            fprintf(stderr, "%s: illegal string constant %s in skipchars binding\n", Whoami, pv->value.s);
  941. X            break;
  942. X        }
  943. X    if (pb = profile_has_binding(ps, "mapctrlsequence")) {
  944. X    for (count = 0, pv = pb->value; pv; pv = pv->next, count++)
  945. X        if (pv->class != PROFILE_OTHER || pv->class != PROFILE_STRING)
  946. X        switch (pv->class) {
  947. X        case PROFILE_INTEGER:
  948. X            fprintf(stderr, "%s: illegal integer constant %d in mapctrlsequence binding\n", Whoami, pv->value.i);
  949. X            break;
  950. X        case PROFILE_HEX:
  951. X            fprintf(stderr, "%s: illegal hex constant 0x%x in mapctrlsequence binding\n", Whoami, pv->value.i);
  952. X            break;
  953. X        case PROFILE_OCTAL:
  954. X            fprintf(stderr, "%s: illegal octal constant 0%o in mapctrlsequence binding\n", Whoami, pv->value.i);
  955. X            break;
  956. X        case PROFILE_FLOAT:
  957. X            fprintf(stderr, "%s: illegal float constant %f in mapctrlsequence binding\n", Whoami, pv->value.f);
  958. X            break;
  959. X        case PROFILE_CHARACTER:
  960. X            fprintf(stderr, "%s: illegal character constant %c in mapctrlsequence binding\n", Whoami, pv->value.c);
  961. X            break;
  962. X        }
  963. X    if (odd(count))
  964. X        fprintf(stderr, "%s: must have an even number of string values for mapctrlsequence binding\n", Whoami);
  965. X    }
  966. X    if (pb = profile_has_binding(ps, "mapindexentry")) {
  967. X    for (count = 0, pv = pb->value; pv; pv = pv->next, count++)
  968. X        if (pv->class != PROFILE_OTHER || pv->class != PROFILE_STRING)
  969. X        switch (pv->class) {
  970. X        case PROFILE_INTEGER:
  971. X            fprintf(stderr, "%s: illegal integer constant %d in mapindexentry binding\n", Whoami, pv->value.i);
  972. X            break;
  973. X        case PROFILE_HEX:
  974. X            fprintf(stderr, "%s: illegal hex constant 0x%x in mapindexentry binding\n", Whoami, pv->value.i);
  975. X            break;
  976. X        case PROFILE_OCTAL:
  977. X            fprintf(stderr, "%s: illegal octal constant 0%o in mapindexentry binding\n", Whoami, pv->value.i);
  978. X            break;
  979. X        case PROFILE_FLOAT:
  980. X            fprintf(stderr, "%s: illegal float constant %f in mapindexentry binding\n", Whoami, pv->value.f);
  981. X            break;
  982. X        case PROFILE_CHARACTER:
  983. X            fprintf(stderr, "%s: illegal character constant %c in mapindexentry binding\n", Whoami, pv->value.c);
  984. X            break;
  985. X        }
  986. X    if (odd(count))
  987. X        fprintf(stderr, "%s: must have an even number of string values for mapindexentry binding\n", Whoami);
  988. X    }
  989. X}
  990. X
  991. X/* Returns the literal string of a token list */
  992. Xchar    *literalstring(t)
  993. Xstruct Token    *t;
  994. X{
  995. X    static char    literal[81];
  996. X
  997. X    strcpy(literal, "");
  998. X    for (t = CurKey; t; t = t->next)
  999. X        strcat(literal, t->lexeme);
  1000. X    return literal;
  1001. X}
  1002. X
  1003. X/* Returns alphabetization string for a token list and a stanza */
  1004. Xchar    *alphabetizestring(tokenlist, stanza)
  1005. Xstruct Token    *tokenlist;
  1006. XPROFILE_STANZA    *stanza;
  1007. X{
  1008. X    char        litstring[81];
  1009. X    char        ctrlstring[21];
  1010. X    char        c[2];
  1011. X    static char        alphastring[81];
  1012. X    int            i;
  1013. X    Boolean        add;
  1014. X    struct Token    *t;
  1015. X    PROFILE_BINDING    *pb, *pbchars, *pbctrlsequence;
  1016. X    PROFILE_VALUE    *pv;
  1017. X    
  1018. X    if (!tokenlist)
  1019. X    return NULL;
  1020. X    strcpy(alphastring, "");
  1021. X    if (!stanza) {
  1022. X    for (t = tokenlist; t; t = t->next)
  1023. X        switch (t->type) {
  1024. X        case string:
  1025. X        case integer:
  1026. X        case comma:
  1027. X        case obrace:
  1028. X        case cbrace:
  1029. X        strcat(alphastring, t->lexeme);
  1030. X        break;
  1031. X        }
  1032. X    return alphastring;
  1033. X    } else {
  1034. X    if (pb = profile_has_binding(stanza, "mapindexentry")) {
  1035. X        strcpy(litstring, literalstring(tokenlist));
  1036. X        for (pv = pb->value; pv && pv->next; pv = pv->next, pv = pv->next)
  1037. X        if ((pv->class == PROFILE_STRING || pv->class == PROFILE_OTHER) && (pv->next->class == PROFILE_STRING ||
  1038. X        pv->next->class == PROFILE_OTHER))
  1039. X            if (eq(litstring, pv->value.s)) {
  1040. X            strcpy(alphastring, pv->next->value.s);
  1041. X            return alphastring;
  1042. X            }
  1043. X    } /* end if there is a mapindexentry binding */
  1044. X    pbchars = profile_has_binding(stanza, "skipchars");
  1045. X    pbctrlsequence = profile_has_binding(stanza, "mapctrlsequence");
  1046. X    c[1] = '\0';
  1047. X    for (t = tokenlist; t; t = t->next)
  1048. X        switch (t->type) {
  1049. X        case controlword:
  1050. X        case controlsymbol:
  1051. X        if (pbctrlsequence)
  1052. X            for (pv = pbctrlsequence->value; pv && pv->next; pv = pv->next, pv = pv->next)
  1053. X            if ((pv->class == PROFILE_STRING || pv->class == PROFILE_OTHER) && (pv->next->class == PROFILE_STRING ||
  1054. X            pv->next->class == PROFILE_OTHER))
  1055. X                if (strlen(pv->value.s) > 0) {
  1056. X                if (pv->value.s[0] != '\\')
  1057. X                    sprintf(ctrlstring, "\\%s", pv->value.s);
  1058. X                else
  1059. X                    strcpy(ctrlstring, pv->value.s);
  1060. X                if (eq(ctrlstring, t->lexeme))
  1061. X                    strcat(alphastring, pv->next->value.s);
  1062. X                }
  1063. X        break;
  1064. X        case string:
  1065. X        case integer:
  1066. X        for (i = 0; t->lexeme[i]; i++)
  1067. X            if (pbchars) {
  1068. X            for (add = TRUE, pv = pbchars->value; pv && add; pv = pv->next)
  1069. X                if (pv->class == PROFILE_CHARACTER)
  1070. X                if (pv->value.c == t->lexeme[i])
  1071. X                    add = FALSE;
  1072. X            if (add) {
  1073. X                c[0] = t->lexeme[i];
  1074. X                strcat(alphastring, c);
  1075. X            }
  1076. X            } else {
  1077. X            c[0] = t->lexeme[i];
  1078. X            strcat(alphastring, c);
  1079. X            }
  1080. X        break;
  1081. X        case comma:
  1082. X        c[0] = ',';
  1083. X        goto insert;
  1084. X        case obrace:
  1085. X        c[0] = '{';
  1086. X        goto insert;
  1087. X        case cbrace:
  1088. X        c[0] = '}';
  1089. Xinsert:        if (pbchars) {
  1090. X            for (add = TRUE, pv = pbchars->value; pv && add; pv = pv->next)
  1091. X            if (pv->class == PROFILE_CHARACTER)
  1092. X                if (pv->value.c == c[0])
  1093. X                add = FALSE;
  1094. X            if (add)
  1095. X            strcat(alphastring, c);
  1096. X        } else
  1097. X            strcat(alphastring, c);
  1098. X        break;
  1099. X        }
  1100. X    return alphastring;
  1101. X    }
  1102. X}
  1103. X
  1104. X/* Finds an entry in a table. Returns NULL if not found. */
  1105. Xstruct IndexEntry    *findentry(table, noentries, string)
  1106. Xstruct IndexEntry     *table;
  1107. Xint            noentries;
  1108. Xchar            *string;
  1109. X{
  1110. X    int    i;
  1111. X
  1112. X    if (noentries <= 0)
  1113. X    return NULL;
  1114. X    for (i = 0; i < noentries; i++)
  1115. X    if (eq(string, table[i].literal))
  1116. X        return &table[i];
  1117. X    return NULL;
  1118. X}
  1119. X
  1120. X/* Returns pointer to page number if found, NULL otherwise */
  1121. Xstruct PageNoTable    *findpage(pagearray, elements, pageno)
  1122. Xstruct PageNoTable    *pagearray;
  1123. Xint            elements;
  1124. Xint            pageno;
  1125. X{
  1126. X    int    i;
  1127. X
  1128. X    if (!pagearray)
  1129. X    return NULL;
  1130. X    for (i = 0; i < elements; i++)
  1131. X    if (pagearray[i].number == pageno)
  1132. X        return &pagearray[i];
  1133. X    return NULL;
  1134. X}
  1135. X
  1136. X/* Sorts the entries in the structures */
  1137. Xsort(base, numberelements)
  1138. Xstruct IndexEntry    *base;
  1139. Xint            numberelements;
  1140. X{
  1141. X    int    i;
  1142. X    int numericcompare();
  1143. X    int alphacompare();
  1144. X
  1145. X    for (i = 0; i < numberelements; i++) {
  1146. X    if (base[i].pagenos)
  1147. X        qsort(base[i].pagenos, base[i].pagetablecount, sizeof(struct PageNoTable), numericcompare);
  1148. X    if (base[i].subitem)
  1149. X        sort(base[i].subitem, base[i].subitemcount);    /* recursion! */
  1150. X    }
  1151. X    qsort(base, numberelements, sizeof(struct IndexEntry), alphacompare);
  1152. X}
  1153. X
  1154. X/* Prints out the index entries */
  1155. Xprintindexentries(base, noelements, level)
  1156. Xstruct IndexEntry    *base;
  1157. Xint            noelements;
  1158. Xint            level;
  1159. X{
  1160. X    int        i, j;
  1161. X    Boolean    prevoutput = FALSE;
  1162. X    Boolean    prevrange = FALSE;
  1163. X    char    c;
  1164. X    char    letter = '\0';
  1165. X
  1166. X    if (level > ITEMDEPTH)
  1167. X    return;
  1168. X    for (i = 0; i < noelements; i++) {
  1169. X    if (level == 1)
  1170. X        if (strlen(base[i].alphabetic) > 0)
  1171. X        if (isalpha(base[i].alphabetic[0])) {
  1172. X            if (isupper(c = base[i].alphabetic[0])) 
  1173. X            c = tolower(c);
  1174. X            if (!letter) {
  1175. X            if (Label) {
  1176. X                fprintf(OutputFile, "\\indexspace\n");
  1177. X                fprintf(OutputFile, "\\largeletter{%c}\n", c);
  1178. X            } else if (prevoutput)
  1179. X                fprintf(OutputFile, "\\indexspace\n");
  1180. X            } else if (letter != c) {
  1181. X            fprintf(OutputFile, "\\indexspace\n");
  1182. X            if (Label)
  1183. X                fprintf(OutputFile, "\\largeletter{%c}\n", c);
  1184. X            }
  1185. X            letter = c;
  1186. X        }
  1187. X    prevoutput = TRUE;
  1188. X    for (j = 1; j < level; j++)
  1189. X        fprintf(OutputFile, "  ");
  1190. X    fprintf(OutputFile, "%s %s ", ItemRep[level - 1], base[i].literal);
  1191. X    if (base[i].pagenos) {
  1192. X        for (j = 0; j < base[i].pagetablecount; j++) {
  1193. X        if (j == base[i].pagetablecount - 1)
  1194. X            fprintf(OutputFile, "%d\n", base[i].pagenos[j].number);
  1195. X        else
  1196. X            if (base[i].pagenos[j].range) {
  1197. X            if (!prevrange)
  1198. X                fprintf(OutputFile, "%d--", base[i].pagenos[j].number);
  1199. X            } else
  1200. X            fprintf(OutputFile, "%d, ", base[i].pagenos[j].number);
  1201. X        prevrange = base[i].pagenos[j].range;
  1202. X        }
  1203. X        if (prevrange)
  1204. X        fprintf(stderr, "%s: file %s, %s %s ends with a range\n", Whoami, IdxFileName, ItemRep[level - 1],
  1205. X        base[i].literal);
  1206. X    } else
  1207. X        fprintf(OutputFile, "\n");
  1208. X    if (base[i].subitem)
  1209. X        printindexentries(base[i].subitem, base[i].subitemcount, level + 1);    /* recursion! */
  1210. X    }
  1211. X}
  1212. X
  1213. Xint    numericcompare(e1, e2)
  1214. Xstruct PageNoTable    *e1, *e2;
  1215. X{
  1216. X    if (e1->number == e2->number)
  1217. X    return 0;
  1218. X    else if (e1->number < e2->number)
  1219. X    return -1;
  1220. X    else
  1221. X    return 1;
  1222. X}
  1223. X
  1224. Xint alphacompare(e1, e2)
  1225. Xstruct IndexEntry    *e1, *e2;
  1226. X{
  1227. X    char    s1[81], s2[81];
  1228. X
  1229. X    strcpy(s1, e1->alphabetic), strcpy(s2, e2->alphabetic);
  1230. X    return(strcmp(string_downshift(s1), string_downshift(s2)));
  1231. X}
  1232. !FaR!OuT!
  1233. echo x - indexlex.l
  1234. sed -e 's/^X//' > indexlex.l << '!FaR!OuT!'
  1235. X/* Lex Lexical Analyzer for LaTeX index processor */
  1236. X%{
  1237. X#undef input
  1238. X#define input()    (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(InputFile)) \
  1239. X    ==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
  1240. X%}
  1241. Xletter        [A-Za-z]
  1242. Xinteger        -?[0-9]{1,9}
  1243. Xwhitespace    [ \t\n]
  1244. X%%
  1245. X\\indexentry        {
  1246. X                LineNo = EndLineNo;
  1247. X                return(INDEXENTRY);
  1248. X            }
  1249. X\\{letter}+        {    /* Control word */
  1250. X                LineNo = EndLineNo;
  1251. X                strcpy(yylval.value, yytext);
  1252. X                return(CONTROLSEQUENCE);
  1253. X            }
  1254. X\\[^{letter}]        {    /* Control symbol */
  1255. X                LineNo = EndLineNo;
  1256. X                strcpy(yylval.value, yytext);
  1257. X                return(CONTROLSEQUENCE);
  1258. X            }
  1259. X\%.*\n            LineNo = EndLineNo++;    /* Comment. Don't pass to parser */
  1260. X{integer}        {
  1261. X                LineNo = EndLineNo;
  1262. X                strcpy(yylval.value, yytext);
  1263. X                return(INTEGER);
  1264. X            }
  1265. X\{ |
  1266. X\} |
  1267. X\,            {
  1268. X                LineNo = EndLineNo;
  1269. X                return(yytext[0]);
  1270. X            }
  1271. X{whitespace}+        {
  1272. X                char    *p;    /* Utility variable */
  1273. X
  1274. X                LineNo = EndLineNo;
  1275. X                for (p = yytext; *p; p++)
  1276. X                if (*p == '\n')
  1277. X                    EndLineNo++;
  1278. X                strcpy(yylval.value, yytext);
  1279. X                return(WHITESPACE);
  1280. X            }
  1281. X[^\\\{\}\%\, \t\n0-9]+    {
  1282. X                LineNo = EndLineNo;
  1283. X                strcpy(yylval.value, yytext);
  1284. X                return(STRING);
  1285. X            }
  1286. X%%
  1287. !FaR!OuT!
  1288. if [ ! -d local.include ]
  1289. then
  1290.     mkdir local.include
  1291.     echo mkdir local.include
  1292. fi
  1293. echo x - local.include/glob.h
  1294. sed -e 's/^X//' > local.include/glob.h << '!FaR!OuT!'
  1295. X/* @(#)glob.h    1.1 (TRW) 1/14/86 */
  1296. X#define GLOB_MAX_PATTERN    1024
  1297. X#define GLOB_OK            0
  1298. X#define GLOB_PATTERN_TOO_BIG    -1
  1299. X#define GLOB_PATTERN_EMPTY    -2
  1300. X#define GLOB_BRACKET_MISSING    -3
  1301. X#define GLOB_RANGE_INVERTED    -4
  1302. X#define GLOB_SET_TOO_BIG    -5
  1303. X#define GLOB_EXECUTION_ERROR    -6
  1304. !FaR!OuT!
  1305. if [ ! -d local.include ]
  1306. then
  1307.     mkdir local.include
  1308.     echo mkdir local.include
  1309. fi
  1310. echo x - local.include/profile.h
  1311. sed -e 's/^X//' > local.include/profile.h << '!FaR!OuT!'
  1312. X/* @(#)profile.h    1.1 (TRW) 1/14/86 */
  1313. Xtypedef struct PROFILE_VALUE {
  1314. X    char class;
  1315. X    union {
  1316. X        long int i;
  1317. X        double f;
  1318. X        char c;
  1319. X        char *s;
  1320. X    } value;
  1321. X    struct PROFILE_VALUE *previous;
  1322. X    struct PROFILE_VALUE *next;
  1323. X} PROFILE_VALUE;
  1324. X
  1325. Xtypedef struct PROFILE_BINDING {
  1326. X    char *name;
  1327. X    PROFILE_VALUE *value;
  1328. X    struct PROFILE_BINDING *previous;
  1329. X    struct PROFILE_BINDING *next;
  1330. X} PROFILE_BINDING;
  1331. X
  1332. Xtypedef struct PROFILE_MARKER {
  1333. X    char *text;
  1334. X    struct PROFILE_MARKER *previous;
  1335. X    struct PROFILE_MARKER *next;
  1336. X} PROFILE_MARKER;
  1337. X
  1338. Xtypedef struct PROFILE_STANZA {
  1339. X    PROFILE_MARKER *marker;
  1340. X    PROFILE_BINDING *binding;
  1341. X    struct PROFILE_STANZA *previous;
  1342. X    struct PROFILE_STANZA *next;
  1343. X} PROFILE_STANZA;
  1344. X
  1345. X/* classes */
  1346. X#define PROFILE_INTEGER 01
  1347. X#define PROFILE_FLOAT 02
  1348. X#define PROFILE_STRING 03
  1349. X#define PROFILE_CHARACTER 04
  1350. X#define PROFILE_OTHER 05
  1351. X#define PROFILE_OCTAL 06
  1352. X#define PROFILE_HEX 07
  1353. X
  1354. X/* no single lexical element may exceed this size in characters */
  1355. X#define PROFILE_MAX_TEXT 255
  1356. X
  1357. XPROFILE_STANZA *profile_read_stanza();
  1358. XPROFILE_STANZA *profile_read_profile();
  1359. XPROFILE_MARKER *profile_has_marker();
  1360. XPROFILE_STANZA *profile_has_stanza();
  1361. XPROFILE_BINDING *profile_has_binding();
  1362. XPROFILE_STANZA *profile_stanza_space();
  1363. XPROFILE_MARKER *profile_marker_space();
  1364. XPROFILE_BINDING *profile_binding_space();
  1365. XPROFILE_VALUE *profile_value_space();
  1366. !FaR!OuT!
  1367. if [ ! -d local.include ]
  1368. then
  1369.     mkdir local.include
  1370.     echo mkdir local.include
  1371. fi
  1372. echo x - local.include/standard.h
  1373. sed -e 's/^X//' > local.include/standard.h << '!FaR!OuT!'
  1374. X/* @(#)standard.h    1.1 (TRW) 6/13/84 */
  1375. X#include <local/standenviron.h>
  1376. X#include <local/standtype.h>
  1377. X#include <local/standconst.h>
  1378. X#include <local/standmacro.h>
  1379. !FaR!OuT!
  1380. if [ ! -d local.include ]
  1381. then
  1382.     mkdir local.include
  1383.     echo mkdir local.include
  1384. fi
  1385. echo x - local.include/standconst.h
  1386. sed -e 's/^X//' > local.include/standconst.h << '!FaR!OuT!'
  1387. X/* @(#)standconst.h    1.1 (TRW) 6/13/84 */
  1388. X/* Standard constants. */
  1389. X
  1390. X/*
  1391. X * These are the only values boolean variables may be set to,
  1392. X * or that boolean functions may return.
  1393. X */
  1394. X#define    TRUE 1
  1395. X#define    FALSE 0
  1396. X
  1397. X/*
  1398. X * Program exit status.
  1399. X * These two codes are intended to be used as arguments to the
  1400. X * exit(2) system call.  Obviously, more failure codes may be
  1401. X * defined but for simple programs that need indicate only
  1402. X * success or failure these will suffice.
  1403. X */
  1404. X#define    SUCCEED 0    /* successful program execution    */
  1405. X#define    FAIL 1        /* some error in running program */
  1406. X
  1407. X/* All bits on or off. */
  1408. X#define    ON ~(long)0    /* all bits set    */
  1409. X#define    OFF (long)0    /* all bits off    */
  1410. X
  1411. X/* UNIX file descriptor numbers for standard input, output, and error. */
  1412. X#define    STANDARD_IN 0
  1413. X#define    STANDARD_OUT 1
  1414. X#define    STANDARD_ERROR 2
  1415. X
  1416. X
  1417. X/*
  1418. X * Extreme values.
  1419. X * These constants are the largest and smallest values
  1420. X * that variables of the indicated type may hold.
  1421. X */
  1422. X#if defined(vax) || defined(pyr) || defined(pyramid)
  1423. X#   define MAX_TINY TINY(0x7f)
  1424. X#   define MIN_TINY TINY(0x80)
  1425. X
  1426. X#   define MAX_UNSIGNED_TINY UNSIGNED_TINY(0xff)
  1427. X#   define MIN_UNSIGNED_TINY 0
  1428. X
  1429. X#   define MAX_SHORT ((short)0x7fff)
  1430. X#   define MIN_SHORT ((short)0x8000)
  1431. X
  1432. X#   define MAX_UNSIGNED_SHORT 0xffff
  1433. X#   define MIN_UNSIGNED_SHORT 0
  1434. X
  1435. X#   define MAX_INTEGER 0x7fffffff
  1436. X#   define MIN_INTEGER 0x80000000
  1437. X
  1438. X#   define MAX_UNSIGNED_INTEGER 0xffffffff
  1439. X#   define MIN_UNSIGNED_INTEGER 0
  1440. X
  1441. X#   define MAX_LONG ((long)0x7fffffff)
  1442. X#   define MIN_LONG ((long)0x80000000)
  1443. X#   define MAX_UNSIGNED_LONG 0xffffffff
  1444. X#   define MIN_UNSIGNED_LONG 0
  1445. X#   define BITS_PER_BYTE 8
  1446. X#endif
  1447. X
  1448. X/* for pointers */
  1449. X#define NIL ((long)0)
  1450. !FaR!OuT!
  1451. if [ ! -d local.include ]
  1452. then
  1453.     mkdir local.include
  1454.     echo mkdir local.include
  1455. fi
  1456. echo x - local.include/standenviron.h
  1457. sed -e 's/^X//' > local.include/standenviron.h << '!FaR!OuT!'
  1458. X/* @(#)standenviron    1.1 (TRW) 6/13/84 */
  1459. X/*
  1460. X * This file defines the machine/compiler C environment. It defines
  1461. X * pre-processor macros that tell what C features are supported.
  1462. X *
  1463. X * #define HAS_UNSIGNED_SHORT    Implies unsigned shorts are supported
  1464. X * #define CHAR_IS_SIGNED    Implies chars are signed
  1465. X * #define HAS_UNSIGNED_CHAR    Implies unsigned chars are supported
  1466. X * #define HAS_UNSIGNED_LONG    Implies unsigned longs are supported
  1467. X * #define BITS_PER_CHAR n    Number of bits in a char
  1468. X * #define BITS_PER_INT n    Number of bits in an int
  1469. X * #define BITS_PER_LONG n    Number of bits in a long
  1470. X * #define BITS_PER_POINTER n    Number of bits in a pointer
  1471. X * #define BITS_PER_SHORT n    Number of bits in a short
  1472. X * #define HAS_VOID        Implies void function type is supported
  1473. X */
  1474. X
  1475. X#ifndef    STANDARD_ENVIRON    /* prevent multiple inclusions    */
  1476. X
  1477. X#if defined(vax) || defined(pyr) || defined(pyramid)
  1478. X#   define HAS_UNSIGNED_SHORT
  1479. X#   define CHAR_IS_SIGNED
  1480. X#   define HAS_UNSIGNED_CHAR
  1481. X#   define HAS_UNSIGNED_LONG
  1482. X#   define HAS_VOID
  1483. X
  1484. X#   define BITS_PER_CHAR 8
  1485. X#   define BITS_PER_INT 32
  1486. X#   define BITS_PER_LONG 32
  1487. X#   define BITS_PER_POINTER 32
  1488. X#   define BITS_PER_SHORT 16
  1489. X#   define STANDARD_ENVIRON
  1490. X#endif
  1491. X
  1492. X#ifdef MC68000
  1493. X#   include "MC68000 unimplemented"
  1494. X#   define STANDARD_ENVIRON
  1495. X#endif MC6800
  1496. X
  1497. X/* make sure a known processor type was    specified */
  1498. X#ifndef    STANDARD_ENVIRON
  1499. X#   include "Processor type unknown or unspecified"
  1500. X#endif STANDARD_ENVIRON
  1501. X
  1502. X#endif STANDARD_ENVIRON
  1503. !FaR!OuT!
  1504. if [ ! -d local.include ]
  1505. then
  1506.     mkdir local.include
  1507.     echo mkdir local.include
  1508. fi
  1509. echo x - local.include/standmacro.h
  1510. sed -e 's/^X//' > local.include/standmacro.h << '!FaR!OuT!'
  1511. X/* @(#)standmacro.h    1.1 (TRW) 6/13/84 */
  1512. X/* Maximum of two values. */
  1513. X#define    MAX(x, y) ((x) > (y) ? (x) : (y))
  1514. X
  1515. X/* Minimum of two values. */
  1516. X#define    MIN(x, y) ((x) < (y) ? (x) : (y))
  1517. X
  1518. X/* Absolute value. */
  1519. X#define    ABS(x) ((x) < 0 ? -(x) : (x))
  1520. !FaR!OuT!
  1521. if [ ! -d local.include ]
  1522. then
  1523.     mkdir local.include
  1524.     echo mkdir local.include
  1525. fi
  1526. echo x - local.include/standtype.h
  1527. sed -e 's/^X//' > local.include/standtype.h << '!FaR!OuT!'
  1528. X/* @(#)standtype.h    1.1 (TRW) 6/13/84 */
  1529. X/* Standard machine independent type definitions. */
  1530. X
  1531. X#ifndef    STANDARD_TYPE    /* prevent multiple inclusions    */
  1532. X#define    STANDARD_TYPE
  1533. X
  1534. X/*
  1535. X * Integers
  1536. X *     Tiny/UnsignedTiny    8+ bit integers
  1537. X *     Short/UnsignedShort    16+ bit integers
  1538. X *     Integer/UnsignedInteger    natural machine integer size
  1539. X *     Long/UnsignedLong    32+ bit integers
  1540. X *
  1541. X * Bits
  1542. X *     TinyBits        8+ bits
  1543. X *     Bits        16+ bits
  1544. X *     LongBits        32+ bits
  1545. X *
  1546. X * Booleans
  1547. X *     TinyBoolean
  1548. X *     Boolean
  1549. X *
  1550. X * Void
  1551. X *
  1552. X * Storage Classes
  1553. X *     Export        Seen in other compilation units
  1554. X *     Import        Supplied by another compilation unit
  1555. X *     Local        Unseen outside compilation unit
  1556. X */
  1557. X
  1558. X/*
  1559. X * Each of the following sections for the integer types defines both
  1560. X * a base type and an extraction macro for the value.
  1561. X */
  1562. X
  1563. X/* Not all machines have signed characters so we may have to simulate them. */
  1564. X#ifdef CHAR_IS_SIGNED
  1565. X    typedef char Tiny;
  1566. X#   define TINY(x) (x)
  1567. X#else
  1568. X    typedef char Tiny;
  1569. X#   define TINY(x) (((x) & 0x80) ? (~0x7f | (x)) : (x))
  1570. X#endif CHAR_IS_SIGNED
  1571. X
  1572. X/* Not all compilers support unsigned chars so we may have to simulate them. */
  1573. X#ifdef HAS_UNSIGNED_CHAR
  1574. X    typedef unsigned char UnsignedTiny;
  1575. X#   define UNSIGNED_TINY(x) (x)
  1576. X#else
  1577. X    typedef char UnsignedTiny;
  1578. X#   define UNSIGNED_TINY(x) ((x) & 0xff)
  1579. X#endif HAS_UNSIGNED_CHAR
  1580. X
  1581. X/*
  1582. X * All compilers have signed short integers.  This type is included
  1583. X * for lexical consistency.
  1584. X */
  1585. Xtypedef short Short;
  1586. X
  1587. X/* Not all compilers support unsigned shorts so we may have to simulate them. */
  1588. X#ifdef HAS_UNSIGNED_SHORT
  1589. X    typedef unsigned short UnsignedShort;
  1590. X#   define UNSIGNED_SHORT(x) (x)
  1591. X#else
  1592. X    typedef short UnsignedShort;
  1593. X#   define UNSIGNED_SHORT(x) ((unsigned)((x) & 0xffff))
  1594. X#endif
  1595. X
  1596. X/* These types are solely for lexical consistency. */
  1597. Xtypedef int Integer;
  1598. Xtypedef    unsigned int UnsignedInteger;
  1599. X
  1600. Xtypedef long Long;
  1601. X
  1602. X/* Not all compilers support unsigned longs so we may have to simulate them. */
  1603. X#ifdef HAS_UNSIGNED_LONG
  1604. X    typedef unsigned long UnsignedLong;
  1605. X#   define UNSIGNED_LONG(x) (x)
  1606. X#else
  1607. X    typedef long UnsignedLong;
  1608. X#   define UNSIGNED_LONG(x) ((long)((x) & 0x7fffffff))
  1609. X#endif HAS_UNSIGNED_LONG
  1610. X
  1611. X/* Boolean types take on only the values TRUE or FALSE. */
  1612. Xtypedef    char TinyBoolean;
  1613. Xtypedef    short Boolean;
  1614. X
  1615. X/* This type is included for lexical consistency. */
  1616. Xtypedef char Character;
  1617. X
  1618. X/* Bit types are used only for bit set, clear and test operations. */
  1619. Xtypedef    char TinyBits;
  1620. Xtypedef    short Bits;
  1621. Xtypedef    long LongBits;
  1622. X
  1623. X/* Not all compilers support void functions so we may have to simulate it. */
  1624. X#ifdef HAS_VOID
  1625. X#   define Void void
  1626. X#else
  1627. X    typedef int Void;
  1628. X#endif
  1629. X
  1630. X/* Storage classes. */
  1631. X#define    Export
  1632. X#define Import extern
  1633. X#define    Local static
  1634. X
  1635. X#endif    STANDARD_TYPE
  1636. !FaR!OuT!
  1637. if [ ! -d local.include ]
  1638. then
  1639.     mkdir local.include
  1640.     echo mkdir local.include
  1641. fi
  1642. echo x - local.include/universe.h
  1643. sed -e 's/^X//' > local.include/universe.h << '!FaR!OuT!'
  1644. Xstruct    universe { /* see getunent(3) */
  1645. X    char    *un_name;
  1646. X    char    *un_universe;
  1647. X};
  1648. X
  1649. Xstruct universe *getunent(), *getunnam();
  1650. !FaR!OuT!
  1651. exit
  1652. -- 
  1653.         Scott Simpson
  1654.         TRW Electronics and Defense Sector
  1655.         ...{decvax,ihnp4,ucbvax}!trwrb!simpson
  1656.  
  1657.  
  1658.