home *** CD-ROM | disk | FTP | other *** search
- From: simpson@trwrb.UUCP (Scott Simpson)
- Newsgroups: comp.sources.misc
- Subject: LaTeX Index Processor (Part 1 of 2)
- Message-ID: <2836@ncoast.UUCP>
- Date: 10 Jul 87 02:02:01 GMT
- Sender: allbery@ncoast.UUCP
- Lines: 1689
- Approved: allbery@ncoast.UUCP
- X-Archive: comp.sources.misc/8707/40
-
- This is a repost of the LaTeX index processor I posted ages ago.
- Thanks to John Renner (adobe!renner@decwrl.dec.com) it now handles
- roman numeral page numbering too. It does not handle upper case
- roman numeral page numbering though. You might want to install the
- libraries distributed with it, especially the profile library. It is
- quite useful. To make it, type "make install". Don't worry, it
- won't actually install anything.
- Scott Simpson
- TRW Electronics and Defense Sector
- ...{decvax,ihnp4,ucbvax}!trwrb!simpson
-
- #! /bin/sh
- # To extract, remove mail header lines and type "sh filename"
- echo x - Makefile
- sed -e 's/^X//' > Makefile << '!FaR!OuT!'
- X# $Header$
- XCFLAGS=-O
- X
- Xall: getopt.o shift.o
- X cd libglob;make all
- X cd libprofile;make all
- X cd indexsrc;make all
- X
- Xinstall: all
- X mv indexsrc/index .
- X
- Xclean:
- X -rm index getopt.o shift.o
- X cd libglob;make clean
- X cd libprofile;make clean
- X cd indexsrc;make clean
- !FaR!OuT!
- echo x - getopt.c
- sed -e 's/^X//' > getopt.c << '!FaR!OuT!'
- X/* @(#)getopt.c 2.1 (TRW) 3/8/86 */
- X#include <stdio.h>
- X
- X/*
- X * get option letter from argument vector
- X */
- Xint opterr = 1, /* useless, never set or used */
- X optind = 1, /* index into parent argv vector */
- X optopt; /* character checked for validity */
- Xchar *optarg; /* argument associated with option */
- X
- X#define BADCH (int)'?'
- X#define EMSG ""
- X#define tell(s) fputs(*nargv,stderr);fputs(s,stderr); \
- X fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
- X
- Xgetopt(nargc,nargv,ostr)
- Xint nargc;
- Xchar **nargv,
- X *ostr;
- X{
- X static char *place = EMSG; /* option letter processing */
- X register char *oli; /* option letter list index */
- X char *index();
- X
- X if(!*place) { /* update scanning pointer */
- X if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) return(EOF);
- X if (*place == '-') { /* found "--" */
- X ++optind;
- X return(EOF);
- X }
- X } /* option letter okay? */
- X if ((optopt = (int)*place++) == (int)':' || !(oli = index(ostr,optopt))) {
- X if(!*place) ++optind;
- X tell(": illegal option -- ");
- X }
- X if (*++oli != ':') { /* don't need argument */
- X optarg = NULL;
- X if (!*place) ++optind;
- X }
- X else { /* need an argument */
- X if (*place) optarg = place; /* no white space */
- X else if (nargc <= ++optind) { /* no arg */
- X place = EMSG;
- X tell(": option requires an argument -- ");
- X }
- X else optarg = nargv[optind]; /* white space */
- X place = EMSG;
- X ++optind;
- X }
- X return(optopt); /* dump back option letter */
- X}
- !FaR!OuT!
- if [ ! -d include.local ]
- then
- mkdir include.local
- echo mkdir include.local
- fi
- echo x - include.local/standard.h
- sed -e 's/^X//' > include.local/standard.h << '!FaR!OuT!'
- X/* $Header */
- X#include "standenviron.h"
- X#include "standconst.h"
- X#include "standtype.h"
- X#include "standmacro.h"
- !FaR!OuT!
- if [ ! -d include.local ]
- then
- mkdir include.local
- echo mkdir include.local
- fi
- echo x - include.local/standconst.h
- sed -e 's/^X//' > include.local/standconst.h << '!FaR!OuT!'
- X/* $Header */
- X/* Standard constants. */
- X#ifndef STANDARD_CONST
- X#define STANDARD_CONST
- X
- X/*
- X * These are the only values boolean variables may be set to,
- X * or that boolean functions may return.
- X */
- X#define TRUE 1
- X#define FALSE 0
- X
- X/*
- X * Program exit status.
- X * These two codes are intended to be used as arguments to the
- X * exit(2) system call. Obviously, more failure codes may be
- X * defined but for simple programs that need indicate only
- X * success or failure these will suffice.
- X */
- X#define SUCCEED 0 /* successful program execution */
- X#define FAIL 1 /* some error in running program */
- X
- X/* All bits on or off. */
- X#define ON ~(long)0 /* all bits set */
- X#define OFF (long)0 /* all bits off */
- X
- X/* UNIX file descriptor numbers for standard input, output, and error. */
- X#define STANDARD_IN 0
- X#define STANDARD_OUT 1
- X#define STANDARD_ERROR 2
- X
- X/*
- X * Extreme values.
- X * These constants are the largest and smallest values
- X * that variables of the indicated type may hold.
- X */
- X#if defined(vax) || defined(pyr)
- X# define MAX_TINY 0x7f
- X# define MIN_TINY 0x80
- X
- X# define MAX_UNSIGNED_TINY 0xff
- X# define MIN_UNSIGNED_TINY 0
- X
- X# define MAX_SHORT 0x7fff
- X# define MIN_SHORT 0x8000
- X
- X# define MAX_UNSIGNED_SHORT 0xffff
- X# define MIN_UNSIGNED_SHORT 0
- X
- X# define MAX_INTEGER 0x7fffffff
- X# define MIN_INTEGER 0x80000000
- X
- X# define MAX_UNSIGNED_INTEGER 0xffffffff
- X# define MIN_UNSIGNED_INTEGER 0
- X
- X# define MAX_LONG MAX_INTEGER
- X# define MIN_LONG MIN_INTEGER
- X# define MAX_UNSIGNED_LONG MAX_UNSIGNED_INTEGER
- X# define MIN_UNSIGNED_LONG MIN_UNSIGNED_INTEGER
- X# define BITS_PER_BYTE 8
- X#endif
- X
- X/* for pointers */
- X#define NIL ((long)0)
- X#endif STANDARD_CONST
- !FaR!OuT!
- if [ ! -d include.local ]
- then
- mkdir include.local
- echo mkdir include.local
- fi
- echo x - include.local/standenviron.h
- sed -e 's/^X//' > include.local/standenviron.h << '!FaR!OuT!'
- X/* $Header */
- X/*
- X * This file defines the machine/compiler C environment. It defines
- X * pre-processor macros that tell what C features are supported.
- X *
- X * #define HAS_UNSIGNED_SHORT Implies unsigned shorts are supported
- X * #define CHAR_IS_SIGNED Implies chars are signed
- X * #define HAS_UNSIGNED_CHAR Implies unsigned chars are supported
- X * #define HAS_UNSIGNED_LONG Implies unsigned longs are supported
- X * #define BITS_PER_CHAR n Number of bits in a char
- X * #define BITS_PER_INT n Number of bits in an int
- X * #define BITS_PER_LONG n Number of bits in a long
- X * #define BITS_PER_POINTER n Number of bits in a pointer
- X * #define BITS_PER_SHORT n Number of bits in a short
- X * #define HAS_VOID Implies void function type is supported
- X */
- X
- X#ifndef STANDARD_ENVIRON /* prevent multiple inclusions */
- X
- X#if defined(vax) || defined(pyr)
- X# define HAS_UNSIGNED_SHORT
- X# define CHAR_IS_SIGNED
- X# define HAS_UNSIGNED_CHAR
- X# define HAS_UNSIGNED_LONG
- X# define HAS_VOID
- X
- X# define BITS_PER_CHAR 8
- X# define BITS_PER_SHORT 16
- X# define BITS_PER_INT 32
- X# define BITS_PER_LONG 32
- X# define BITS_PER_POINTER 32
- X# define STANDARD_ENVIRON
- X#endif
- X
- X#endif STANDARD_ENVIRON
- X
- X/* make sure a known processor type was specified */
- X#ifndef STANDARD_ENVIRON
- X# include "Processor type unknown or unspecified"
- X#endif STANDARD_ENVIRON
- !FaR!OuT!
- if [ ! -d include.local ]
- then
- mkdir include.local
- echo mkdir include.local
- fi
- echo x - include.local/standmacro.h
- sed -e 's/^X//' > include.local/standmacro.h << '!FaR!OuT!'
- X/* $Header */
- X#ifndef STANDARD_MACRO
- X#define STANDARD_MACRO
- X#define MAX(x, y) ((x) > (y) ? (x) : (y))
- X#define MIN(x, y) ((x) < (y) ? (x) : (y))
- X#define ABS(x) ((x) < 0 ? -(x) : (x))
- X#define ROUND(x) ((int)(((x)<0)?((x)-0.5):((x)+0.5)))
- X#define CEILING(x) (((x)>=0)?(int)(x)==(x)?(int)(x):(int)((x)+1):(int)(x))
- X#define FLOOR(x) (((x)>=0)?(int)(x):(int)(x)==(x)?(int)(x):(int)((x)-1))
- X#define EQ(s, t) (!strcmp(s, t))
- X#define EQN(s, t, n) (!strncmp(s, t, n))
- X#endif STANDARD_MACRO
- !FaR!OuT!
- if [ ! -d include.local ]
- then
- mkdir include.local
- echo mkdir include.local
- fi
- echo x - include.local/standtype.h
- sed -e 's/^X//' > include.local/standtype.h << '!FaR!OuT!'
- X/* $Header */
- X/* Standard machine independent type definitions. */
- X
- X#ifndef STANDARD_TYPE /* prevent multiple inclusions */
- X#define STANDARD_TYPE
- X
- X/*
- X * Integers
- X * Tiny/UnsignedTiny 8+ bit integers
- X * Short/UnsignedShort 16+ bit integers
- X * Integer/UnsignedInteger natural machine integer size
- X * Long/UnsignedLong 32+ bit integers
- X *
- X * Bits
- X * TinyBits 8+ bits
- X * Bits 16+ bits
- X * LongBits 32+ bits
- X *
- X * Booleans
- X * TinyBoolean
- X * Boolean
- X *
- X * Void
- X *
- X * Storage Classes
- X * Export Seen in other compilation units
- X * Import Supplied by another compilation unit
- X * Local Unseen outside compilation unit
- X */
- X
- X/*
- X * Each of the following sections for the integer types defines both
- X * a base type and an extraction macro for the value.
- X */
- X
- Xtypedef char Tiny;
- X/* Not all machines have signed characters so we may have to simulate them. */
- X#ifdef CHAR_IS_SIGNED
- X# define TINY(x) (x)
- X#else
- X# define TINY(x) (((x) & MIN_TINY) ? (~MAX_TINY | (x)) : (x))
- X#endif CHAR_IS_SIGNED
- X
- X/* Not all compilers support unsigned chars so we may have to simulate them. */
- X#ifdef HAS_UNSIGNED_CHAR
- X typedef unsigned char UnsignedTiny;
- X#else
- X typedef char UnsignedTiny;
- X#endif HAS_UNSIGNED_CHAR
- X#ifdef CHAR_IS_SIGNED
- X# define UNSIGNED_TINY(x) ((x) & MAX_UNSIGNED_TINY)
- X#else
- X# define UNSIGNED_TINY(x) (x)
- X#endif
- X
- X/*
- X * All compilers have signed short integers. This type is included
- X * for lexical consistency.
- X */
- Xtypedef short Short;
- X
- X/* Not all compilers support unsigned shorts so we may have to simulate them. */
- X#ifdef HAS_UNSIGNED_SHORT
- X typedef unsigned short UnsignedShort;
- X#else
- X typedef short UnsignedShort;
- X#endif
- X# define UNSIGNED_SHORT(x) ((unsigned)(x) & MAX_UNSIGNED_SHORT)
- X
- X/* These types are solely for lexical consistency. */
- Xtypedef int Integer;
- Xtypedef unsigned int UnsignedInteger;
- X
- Xtypedef long Long;
- X
- X/* Not all compilers support unsigned longs so we may have to simulate them. */
- X#ifdef HAS_UNSIGNED_LONG
- X typedef unsigned long UnsignedLong;
- X# define UNSIGNED_LONG(s) ((UnsignedLong)(x))
- X#else
- X typedef long UnsignedLong;
- X# define UNSIGNED_LONG(x) ((long)(x) & MAX_LONG)
- X#endif HAS_UNSIGNED_LONG
- X
- X/* Boolean types take on only the values TRUE or FALSE. */
- Xtypedef char TinyBoolean;
- Xtypedef short Boolean;
- X
- X/* This type is included for lexical consistency. */
- Xtypedef char Character;
- X
- X/* Bit types are used only for bit set, clear and test operations. */
- Xtypedef char TinyBits;
- Xtypedef short Bits;
- Xtypedef long LongBits;
- X
- X/* Not all compilers support void functions so we may have to simulate it. */
- X#ifdef HAS_VOID
- X# define Void void
- X#else
- X typedef int Void;
- X#endif
- X
- X/* Storage classes. */
- X#define Export
- X#define Import extern
- X#define Local static
- X
- X#endif STANDARD_TYPE
- !FaR!OuT!
- if [ ! -d indexsrc ]
- then
- mkdir indexsrc
- echo mkdir indexsrc
- fi
- echo x - indexsrc/Makefile
- sed -e 's/^X//' > indexsrc/Makefile << '!FaR!OuT!'
- X# $Header: Makefile,v 1.1 86/06/10 08:25:26 control Exp $
- XLDFLAGS=-s
- XCFLAGS=-O -I../libglob -I../libprofile -I../include.local
- X
- Xall: index
- X
- Xindex: indexlex.c index.o
- X $(CC) $(CFLAGS) $(LDFLAGS) -o index index.o ../getopt.o ../shift.o \
- X ../libprofile/libprofile.a ../libglob/libglob.a -ll
- X
- Xindexlex.c: indexlex.l
- X
- Xindex.o: indexlex.c
- X
- Xinstall: all
- X
- Xclean:
- X -rm *.o lex.yy.c y.tab.c indexlex.c index
- !FaR!OuT!
- if [ ! -d indexsrc ]
- then
- mkdir indexsrc
- echo mkdir indexsrc
- fi
- echo x - indexsrc/index.y
- sed -e 's/^X//' > indexsrc/index.y << '!FaR!OuT!'
- X/* $Header */
- X/* Yacc parser for LaTeX index processor */
- X/* Roman numeral code written by John Renner (adobe!renner@decwrl.dec.com) */
- X%{
- X#include <stdio.h>
- X#include "standard.h"
- X#include "profile.h"
- X#include <ctype.h>
- X#include <pwd.h>
- X#define TABLEINCREMENT 50 /* Number of additional entries added when expanding a table */
- X#define eq(s,t) (!strcmp((s),(t)))
- X#define odd(i) (((i) % 2) == 1)
- X#define ITEMDEPTH 3 /* Number of nestings of \item's, \subitem's, \subsubitem's, etc. */
- Xchar *ItemRep[] = { "\\item", "\\subitem", "\\subsubitem", NULL }; /* and their representation */
- Xchar *calloc(), *realloc();
- Xenum TokenType {controlword, controlsymbol, string, integer, roman, comma, obrace, cbrace, whitespace};
- Xstruct IndexEntry {
- X char literal[81]; /* Literal representation of index entry */
- X char alphabetic[81]; /* Alphabetic representation for sorting of index entry */
- X struct Token *tokenlist; /* Doubly linked token list */
- X struct IndexEntry *subitem; /* Pointer to subitem table, subsubitem table, etc */
- X int subitemcount; /* Number of items in subitem table */
- X int subitemtabsize; /* Subitem table size currently allocated */
- X struct PageNoTable *pagenos; /* List of page numbers */
- X int pagetablecount; /* Number of items in page number table */
- X int pagetablesize; /* Size of page number table currently allocated */
- X};
- Xstruct Token {
- X enum TokenType type; /* Token type */
- X char lexeme[81]; /* Representation of all the token types */
- X struct Token *prev, *next;
- X};
- Xstruct PageNoTable {
- X int number; /* Page number */
- X Boolean range; /* True if this is the beginning of a range */
- X Boolean isroman; /* True if this was a roman numeral */
- X};
- Xstruct IndexEntry *IndexTable = NULL; /* Table of primary index entries */
- Xint IndexTableCount = 0; /* Count of number of elements used in index table */
- Xint IndexTableSize = 0; /* Current allocated size of index table */
- Xint ExitStatus = SUCCEED; /* Guess */
- Xint LineNo = 1; /* Line number at start of token */
- Xint EndLineNo = 1; /* Line number at end of token */
- XBoolean Label = FALSE; /* True if -l option given */
- XBoolean Range; /* True if this \indexentry is a range */
- XPROFILE_STANZA *SortStanza = NULL; /* Alphabetize stanza */
- Xextern int optind; /* From getopt(3) */
- Xextern char *optarg;
- Xchar *Whoami; /* argv[0] */
- Xchar *Usage = "Usage: %s [-l] [-f alphabetizefile] [file...]\n";
- Xchar *Marker[] = { "alphabetize", NULL }; /* Markers for alphabetize stanza */
- Xchar IdxFileName[81]; /* .idx file name */
- Xchar Literal[81]; /* Literal string of key */
- Xchar Alphabetic[81]; /* Alphabetic string of key */
- XFILE *InputFile; /* Current input file */
- XFILE *OutputFile; /* Current output file */
- Xstruct Token *CurKey; /* Current key we are constructing */
- Xstruct IndexEntry **CurSearchTable; /* Current table to search for match */
- Xstruct IndexEntry *CurEntry; /* Current table entry */
- Xstruct IndexEntry *PrevEntry; /* Previous Entry */
- X%}
- X%union {
- X char value[81];
- X struct Token *t;
- X}
- X%token <value> ROMAN CONTROLSEQUENCE INTEGER WHITESPACE STRING INDEXENTRY
- X%type <t> noncommaelement anyelement anyelements
- X%%
- Xindexfile :
- X optwhitespace
- X indexentries
- X {
- X sort(IndexTable, IndexTableCount);
- X fprintf(OutputFile, "\\begin{theindex}\n");
- X if (Label) {
- X fprintf(OutputFile,
- X "\\newcommand{\\largeletter}[1]{{\\pagebreak[2]\\Large\\hspace{-.5in}\\parbox[t]{.5in}{\\makebox[.35in][r]");
- X fprintf(OutputFile, "{\\uppercase{#1}}}\\nopagebreak[4]\\vspace{-1.5ex}}}\n");
- X }
- X printindexentries(IndexTable, IndexTableCount, 1);
- X fprintf(OutputFile, "\\end{theindex}\n");
- X }
- X ;
- X
- Xindexentries :
- X indexentries
- X indexentry
- X |
- X indexentry
- X ;
- X
- Xindexentry :
- X INDEXENTRY
- X {
- X CurSearchTable = &IndexTable, PrevEntry = NULL;
- X CurKey = NULL;
- X Range = FALSE;
- X }
- X optwhitespace
- X '{'
- X keys
- X '}'
- X optwhitespace
- X '{'
- X optwhitespace
- X anumber
- X optwhitespace
- X '}'
- X optwhitespace
- X ;
- X
- Xanumber :
- X INTEGER
- X {
- X struct PageNoTable *p;
- X
- X if (!(p = findpage(CurEntry->pagenos, CurEntry->pagetablecount, atoi($1), FALSE))) {
- X if (CurEntry->pagetablecount >= CurEntry->pagetablesize) {
- X if (!(CurEntry->pagenos = (struct PageNoTable *)reallocate(CurEntry->pagenos, CurEntry->pagetablesize,
- X TABLEINCREMENT, sizeof(struct PageNoTable)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X CurEntry->pagetablesize += TABLEINCREMENT;
- X }
- X CurEntry->pagenos[CurEntry->pagetablecount].number = atoi($1);
- X CurEntry->pagenos[CurEntry->pagetablecount].isroman = FALSE;
- X CurEntry->pagenos[CurEntry->pagetablecount].range = Range;
- X CurEntry->pagetablecount++;
- X } else
- X p->range = Range;
- X }
- X |
- X ROMAN
- X {
- X struct PageNoTable *p;
- X
- X if (!(p = findpage(CurEntry->pagenos, CurEntry->pagetablecount, rmtoi($1), TRUE))) {
- X if (CurEntry->pagetablecount >= CurEntry->pagetablesize) {
- X if (!(CurEntry->pagenos = (struct PageNoTable *)reallocate(CurEntry->pagenos, CurEntry->pagetablesize,
- X TABLEINCREMENT, sizeof(struct PageNoTable)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X CurEntry->pagetablesize += TABLEINCREMENT;
- X }
- X CurEntry->pagenos[CurEntry->pagetablecount].number = rmtoi($1);
- X CurEntry->pagenos[CurEntry->pagetablecount].isroman = TRUE;
- X CurEntry->pagenos[CurEntry->pagetablecount].range = Range;
- X CurEntry->pagetablecount++;
- X } else
- X p->range = Range;
- X }
- X
- Xkeys :
- X multiplekeys
- X key
- X {
- X struct Token *t;
- X
- X for (t = CurKey; t->next; t = t->next)
- X ;
- X if (t->type == string)
- X if (t->lexeme[strlen(t->lexeme) - 1] == '-') {
- X t->lexeme[strlen(t->lexeme) - 1] = '\0';
- X Range = TRUE;
- X }
- X goto installkey;
- X }
- X ;
- X
- Xmultiplekeys :
- X multiplekeys
- X key
- X ','
- X {
- X struct Token *t;
- X
- Xinstallkey: strcpy(Literal, literalstring(CurKey));
- X strcpy(Alphabetic, alphabetizestring(CurKey, SortStanza));
- X if (!*CurSearchTable) {
- X if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, 0, TABLEINCREMENT,
- X sizeof(struct IndexEntry)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X if (!PrevEntry)
- X IndexTableSize = TABLEINCREMENT;
- X else
- X PrevEntry->subitemtabsize = TABLEINCREMENT;
- X }
- X if (!(CurEntry = findentry(*CurSearchTable, PrevEntry ? PrevEntry->subitemcount : IndexTableCount, Literal))) {
- X if (!PrevEntry) {
- X if (IndexTableCount >= IndexTableSize) {
- X if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, IndexTableSize, TABLEINCREMENT,
- X sizeof(struct IndexEntry)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X IndexTableSize += TABLEINCREMENT;
- X }
- X CurEntry = (*CurSearchTable + IndexTableCount);
- X IndexTableCount++;
- X } else {
- X if (PrevEntry->subitemcount >= PrevEntry->subitemtabsize) {
- X if (!(*CurSearchTable = (struct IndexEntry *)reallocate(*CurSearchTable, PrevEntry->subitemtabsize,
- X TABLEINCREMENT, sizeof(struct IndexEntry)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X PrevEntry->subitemtabsize += TABLEINCREMENT;
- X }
- X CurEntry = (*CurSearchTable + PrevEntry->subitemcount);
- X PrevEntry->subitemcount++;
- X }
- X strcpy(CurEntry->literal, Literal);
- X strcpy(CurEntry->alphabetic, Alphabetic);
- X CurKey->prev = CurEntry->tokenlist, CurEntry->tokenlist = CurKey;
- X CurEntry->subitem = NULL, CurEntry->subitemcount = CurEntry->subitemtabsize = 0;
- X CurEntry->pagenos = NULL, CurEntry->pagetablecount = CurEntry->pagetablesize = 0;
- X }
- X CurSearchTable = &CurEntry->subitem;
- X PrevEntry = CurEntry;
- X CurKey = NULL;
- X }
- X |
- X /* epsilon */
- X ;
- X
- Xkey :
- X key
- X noncommaelement
- X |
- X noncommaelement
- X ;
- X
- Xnoncommaelement :
- X CONTROLSEQUENCE
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = isalpha($1[1]) ? controlword : controlsymbol;
- X strcpy($$->lexeme, $1);
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X |
- X ROMAN
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = roman;
- X strcpy($$->lexeme, $1);
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X |
- X INTEGER
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = integer;
- X strcpy($$->lexeme, $1);
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X |
- X WHITESPACE
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = whitespace;
- X strcpy($$->lexeme, $1);
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X |
- X STRING
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = string;
- X strcpy($$->lexeme, $1);
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X |
- X '{'
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = obrace;
- X strcpy($$->lexeme, "{");
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X }
- X anyelements
- X '}'
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = cbrace;
- X strcpy($$->lexeme, "}");
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X ;
- X
- Xanyelements :
- X anyelements
- X anyelement
- X {
- X $$ = $2;
- X }
- X |
- X anyelement /* Default action is $$ = $1 */
- X ;
- X
- Xanyelement :
- X noncommaelement /* Default action is $$ = $1 */
- X |
- X ','
- X {
- X if (!($$ = (struct Token *)calloc(1, sizeof(struct Token)))) {
- X yyerror("memory allocation failure");
- X exit(FAIL);
- X }
- X $$->type = comma;
- X strcpy($$->lexeme, ",");
- X $$->next = NULL;
- X if (!CurKey)
- X $$->prev = CurKey, CurKey = $$;
- X else {
- X struct Token *p;
- X
- X for (p = CurKey; p->next; p = p->next)
- X ;
- X p->next = $$, $$->prev = p;
- X }
- X $$ = CurKey;
- X }
- X ;
- X
- Xoptwhitespace :
- X WHITESPACE
- X |
- X ;
- X
- X%%
- X#include "indexlex.c"
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar *argv[];
- X{
- X int c;
- X Boolean sortfilegiven = FALSE;
- X char sortfilename[81];
- X char indfilename[81];
- X struct passwd *pwentry;
- X FILE *stanzafileptr;
- X
- X Whoami = argv[0];
- X pwentry = getpwuid(geteuid());
- X sprintf(sortfilename, "%s/.alphabetize", pwentry->pw_dir);
- X while ((c = getopt(argc, argv, "f:l")) != EOF)
- X switch (c) {
- X case 'l':
- X Label = TRUE;
- X break;
- X case 'f':
- X strcpy(sortfilename, optarg);
- X sortfilegiven = TRUE;
- X break;
- X case '?':
- X fprintf(stderr, Usage, Whoami);
- X exit(FAIL);
- X }
- X stanzafileptr = fopen(sortfilename, "r");
- X if (sortfilegiven && !stanzafileptr) {
- X fprintf(stderr, "%s: cannot open alphabetization file %s\n", Whoami, sortfilename);
- X exit(FAIL);
- X }
- X if (stanzafileptr) {
- X if (!(SortStanza = profile_read_profile(stanzafileptr))) {
- X fprintf(stderr, "%s: file %s is not in stanza format\n", Whoami, sortfilename);
- X fclose(stanzafileptr);
- X exit(FAIL);
- X }
- X if (!(SortStanza = profile_has_stanza(SortStanza, Marker))) {
- X fprintf(stderr, "%s: file %s does not contain a stanza with marker %s\n", Whoami, sortfilename, Marker[0]);
- X fclose(stanzafileptr);
- X exit(FAIL);
- X }
- X fclose(stanzafileptr);
- X }
- X checkstanza(SortStanza);
- X if (optind == argc) {
- X InputFile = stdin;
- X OutputFile = stdout;
- X strcpy(IdxFileName, "stdin");
- X }
- X do {
- X if (InputFile != stdin) {
- X strcpy(IdxFileName, argv[optind]);
- X if (!(InputFile = fopen(argv[optind], "r"))) {
- X strcpy(IdxFileName, argv[optind]);
- X strcat(IdxFileName, ".idx");
- X if (!(InputFile = fopen(IdxFileName, "r"))) {
- X fprintf(stderr, "%s: cannot open %s\n", Whoami, IdxFileName);
- X ExitStatus = FAIL;
- X continue;
- X }
- X }
- X if (strlen(IdxFileName) >= 4 && eq(&IdxFileName[strlen(IdxFileName)-4], ".idx"))
- X sprintf(indfilename, "%.*s.ind", strlen(IdxFileName)-4, IdxFileName);
- X else
- X sprintf(indfilename, "%s.ind", IdxFileName);
- X if (!(OutputFile = fopen(indfilename, "w"))) {
- X fprintf(stderr, "%s: cannot open output file %s\n", Whoami, indfilename);
- X fclose(InputFile);
- X ExitStatus = FAIL;
- X continue;
- X }
- X } else
- X strcpy(IdxFileName, "stdin");
- X if (yyparse() != 0)
- X ExitStatus = FAIL;
- X fclose(InputFile);
- X fclose(OutputFile);
- X freetables(IndexTable, IndexTableCount);
- X IndexTable = NULL, IndexTableCount = IndexTableSize = 0, LineNo = EndLineNo = 1;
- X yysptr = yysbuf; /* Resets Lex lookahead buffer */
- X } while (++optind < argc);
- X exit(ExitStatus);
- X}
- X
- Xyyerror(s)
- Xchar *s;
- X{
- X fprintf(stderr, "\"%s\", line %d: %s\n", IdxFileName, LineNo, s);
- X}
- X
- X/* Allocates additional space for tables. Returns NULL if memory allocation failure or inconsistent parameters */
- Xchar *reallocate(table, current, increment, elementsize)
- Xchar *table; /* pointer to current table */
- Xint current; /* current size of table */
- Xint increment; /* additional entries to add */
- Xint elementsize; /* size of an element in the table */
- X{
- X char *calloc(), *realloc();
- X char *p;
- X
- X if ((!table && current > 0) || current < 0 || increment < 0 || elementsize < 0)
- X return NULL;
- X if (increment == 0 || elementsize == 0)
- X return table;
- X if (current == 0)
- X if (!(p = calloc(increment, elementsize)))
- X return NULL;
- X else
- X return p;
- X else
- X if (!(p = realloc(table, (current + increment) * elementsize)))
- X return NULL;
- X else
- X return p;
- X}
- X
- X/* Frees the space allocated for all the tables */
- Xfreetables(index, noentries)
- Xstruct IndexEntry *index; /* index table */
- Xint noentries; /* number of entries in table */
- X{
- X struct Token *t, *ttemp;
- X int i;
- X
- X if (!index || noentries == 0)
- X return;
- X for (i = 0; i < noentries; i++)
- X if (index[i].subitem)
- X freetables(index[i].subitem, index[i].subitemcount); /* recursion! */
- X for (t = index[i].tokenlist; t; t = ttemp)
- X ttemp = t->next, free(t);
- X if (index[i].pagenos)
- X free(index[i].pagenos);
- X free(index);
- X}
- X
- X/* Checks alphabetize stanza for validity */
- Xcheckstanza(ps)
- XPROFILE_STANZA *ps;
- X{
- X PROFILE_BINDING *pb;
- X PROFILE_VALUE *pv;
- X int count;
- X
- X if (!ps)
- X return;
- X if (pb = profile_has_binding(ps, "skipchars"))
- X for (pv = pb->value; pv; pv = pv->next)
- X if (pv->class != PROFILE_CHARACTER)
- X switch (pv->class) {
- X case PROFILE_INTEGER:
- X fprintf(stderr, "%s: illegal integer constant %d in skipchars binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_HEX:
- X fprintf(stderr, "%s: illegal hex constant 0x%x in skipchars binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_OCTAL:
- X fprintf(stderr, "%s: illegal octal constant 0%o in skipchars binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_FLOAT:
- X fprintf(stderr, "%s: illegal float constant %f in skipchars binding\n", Whoami, pv->value.f);
- X break;
- X case PROFILE_STRING:
- X case PROFILE_OTHER:
- X fprintf(stderr, "%s: illegal string constant %s in skipchars binding\n", Whoami, pv->value.s);
- X break;
- X }
- X if (pb = profile_has_binding(ps, "mapctrlsequence")) {
- X for (count = 0, pv = pb->value; pv; pv = pv->next, count++)
- X if (pv->class != PROFILE_OTHER || pv->class != PROFILE_STRING)
- X switch (pv->class) {
- X case PROFILE_INTEGER:
- X fprintf(stderr, "%s: illegal integer constant %d in mapctrlsequence binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_HEX:
- X fprintf(stderr, "%s: illegal hex constant 0x%x in mapctrlsequence binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_OCTAL:
- X fprintf(stderr, "%s: illegal octal constant 0%o in mapctrlsequence binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_FLOAT:
- X fprintf(stderr, "%s: illegal float constant %f in mapctrlsequence binding\n", Whoami, pv->value.f);
- X break;
- X case PROFILE_CHARACTER:
- X fprintf(stderr, "%s: illegal character constant %c in mapctrlsequence binding\n", Whoami, pv->value.c);
- X break;
- X }
- X if (odd(count))
- X fprintf(stderr, "%s: must have an even number of string values for mapctrlsequence binding\n", Whoami);
- X }
- X if (pb = profile_has_binding(ps, "mapindexentry")) {
- X for (count = 0, pv = pb->value; pv; pv = pv->next, count++)
- X if (pv->class != PROFILE_OTHER || pv->class != PROFILE_STRING)
- X switch (pv->class) {
- X case PROFILE_INTEGER:
- X fprintf(stderr, "%s: illegal integer constant %d in mapindexentry binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_HEX:
- X fprintf(stderr, "%s: illegal hex constant 0x%x in mapindexentry binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_OCTAL:
- X fprintf(stderr, "%s: illegal octal constant 0%o in mapindexentry binding\n", Whoami, pv->value.i);
- X break;
- X case PROFILE_FLOAT:
- X fprintf(stderr, "%s: illegal float constant %f in mapindexentry binding\n", Whoami, pv->value.f);
- X break;
- X case PROFILE_CHARACTER:
- X fprintf(stderr, "%s: illegal character constant %c in mapindexentry binding\n", Whoami, pv->value.c);
- X break;
- X }
- X if (odd(count))
- X fprintf(stderr, "%s: must have an even number of string values for mapindexentry binding\n", Whoami);
- X }
- X}
- X
- X/* Returns the literal string of a token list */
- Xchar *literalstring(t)
- Xstruct Token *t;
- X{
- X static char literal[81];
- X
- X strcpy(literal, "");
- X for (t = CurKey; t; t = t->next)
- X strcat(literal, t->lexeme);
- X return literal;
- X}
- X
- X/* Returns alphabetization string for a token list and a stanza */
- Xchar *alphabetizestring(tokenlist, stanza)
- Xstruct Token *tokenlist;
- XPROFILE_STANZA *stanza;
- X{
- X char litstring[81];
- X char ctrlstring[21];
- X char c[2];
- X static char alphastring[81];
- X int i;
- X Boolean add;
- X struct Token *t;
- X PROFILE_BINDING *pb, *pbchars, *pbctrlsequence;
- X PROFILE_VALUE *pv;
- X
- X if (!tokenlist)
- X return NULL;
- X strcpy(alphastring, "");
- X if (!stanza) {
- X for (t = tokenlist; t; t = t->next)
- X switch (t->type) {
- X case string:
- X case integer:
- X case roman:
- X case comma:
- X case obrace:
- X case cbrace:
- X strcat(alphastring, t->lexeme);
- X break;
- X }
- X return alphastring;
- X } else {
- X if (pb = profile_has_binding(stanza, "mapindexentry")) {
- X strcpy(litstring, literalstring(tokenlist));
- X for (pv = pb->value; pv && pv->next; pv = pv->next, pv = pv->next)
- X if ((pv->class == PROFILE_STRING || pv->class == PROFILE_OTHER) && (pv->next->class == PROFILE_STRING ||
- X pv->next->class == PROFILE_OTHER))
- X if (eq(litstring, pv->value.s)) {
- X strcpy(alphastring, pv->next->value.s);
- X return alphastring;
- X }
- X } /* end if there is a mapindexentry binding */
- X pbchars = profile_has_binding(stanza, "skipchars");
- X pbctrlsequence = profile_has_binding(stanza, "mapctrlsequence");
- X c[1] = '\0';
- X for (t = tokenlist; t; t = t->next)
- X switch (t->type) {
- X case controlword:
- X case controlsymbol:
- X if (pbctrlsequence)
- X for (pv = pbctrlsequence->value; pv && pv->next; pv = pv->next, pv = pv->next)
- X if ((pv->class == PROFILE_STRING || pv->class == PROFILE_OTHER) && (pv->next->class == PROFILE_STRING ||
- X pv->next->class == PROFILE_OTHER))
- X if (strlen(pv->value.s) > 0) {
- X if (pv->value.s[0] != '\\')
- X sprintf(ctrlstring, "\\%s", pv->value.s);
- X else
- X strcpy(ctrlstring, pv->value.s);
- X if (eq(ctrlstring, t->lexeme))
- X strcat(alphastring, pv->next->value.s);
- X }
- X break;
- X case string:
- X case integer:
- X case roman:
- X for (i = 0; t->lexeme[i]; i++)
- X if (pbchars) {
- X for (add = TRUE, pv = pbchars->value; pv && add; pv = pv->next)
- X if (pv->class == PROFILE_CHARACTER)
- X if (pv->value.c == t->lexeme[i])
- X add = FALSE;
- X if (add) {
- X c[0] = t->lexeme[i];
- X strcat(alphastring, c);
- X }
- X } else {
- X c[0] = t->lexeme[i];
- X strcat(alphastring, c);
- X }
- X break;
- X case comma:
- X c[0] = ',';
- X goto insert;
- X case obrace:
- X c[0] = '{';
- X goto insert;
- X case cbrace:
- X c[0] = '}';
- Xinsert: if (pbchars) {
- X for (add = TRUE, pv = pbchars->value; pv && add; pv = pv->next)
- X if (pv->class == PROFILE_CHARACTER)
- X if (pv->value.c == c[0])
- X add = FALSE;
- X if (add)
- X strcat(alphastring, c);
- X } else
- X strcat(alphastring, c);
- X break;
- X }
- X return alphastring;
- X }
- X}
- X
- X/* Finds an entry in a table. Returns NULL if not found. */
- Xstruct IndexEntry *findentry(table, noentries, string)
- Xstruct IndexEntry *table;
- Xint noentries;
- Xchar *string;
- X{
- X int i;
- X
- X if (noentries <= 0)
- X return NULL;
- X for (i = 0; i < noentries; i++)
- X if (eq(string, table[i].literal))
- X return &table[i];
- X return NULL;
- X}
- X
- X/* Returns pointer to page number if found, NULL otherwise */
- Xstruct PageNoTable *findpage(pagearray, elements, pageno, aromannum)
- Xstruct PageNoTable *pagearray;
- Xint elements;
- Xint pageno;
- XBoolean aromannum;
- X{
- X int i;
- X
- X if (!pagearray)
- X return NULL;
- X for (i = 0; i < elements; i++)
- X if ((pagearray[i].number == pageno) &&
- X (pagearray[i].isroman == aromannum))
- X return &pagearray[i];
- X return NULL;
- X}
- X
- X/* Sorts the entries in the structures */
- Xsort(base, numberelements)
- Xstruct IndexEntry *base;
- Xint numberelements;
- X{
- X int i;
- X int numericcompare();
- X int alphacompare();
- X
- X for (i = 0; i < numberelements; i++) {
- X if (base[i].pagenos)
- X qsort(base[i].pagenos, base[i].pagetablecount, sizeof(struct PageNoTable), numericcompare);
- X if (base[i].subitem)
- X sort(base[i].subitem, base[i].subitemcount); /* recursion! */
- X }
- X qsort(base, numberelements, sizeof(struct IndexEntry), alphacompare);
- X}
- X
- X/* Prints out the index entries */
- Xprintindexentries(base, noelements, level)
- Xstruct IndexEntry *base;
- Xint noelements;
- Xint level;
- X{
- X int i, j;
- X Boolean prevoutput = FALSE;
- X Boolean prevrange = FALSE;
- X char c;
- X char letter = '\0';
- X
- X if (level > ITEMDEPTH)
- X return;
- X for (i = 0; i < noelements; i++) {
- X if (level == 1)
- X if (strlen(base[i].alphabetic) > 0)
- X if (isalpha(base[i].alphabetic[0])) {
- X if (isupper(c = base[i].alphabetic[0]))
- X c = tolower(c);
- X if (!letter) {
- X if (Label) {
- X fprintf(OutputFile, "\\indexspace\n");
- X fprintf(OutputFile, "\\largeletter{%c}\n", c);
- X } else if (prevoutput)
- X fprintf(OutputFile, "\\indexspace\n");
- X } else if (letter != c) {
- X fprintf(OutputFile, "\\indexspace\n");
- X if (Label)
- X fprintf(OutputFile, "\\largeletter{%c}\n", c);
- X }
- X letter = c;
- X }
- X prevoutput = TRUE;
- X for (j = 1; j < level; j++)
- X fprintf(OutputFile, " ");
- X fprintf(OutputFile, "%s %s ", ItemRep[level - 1], base[i].literal);
- X if (base[i].pagenos) {
- X for (j = 0; j < base[i].pagetablecount; j++) {
- X if (j == base[i].pagetablecount - 1) {
- X if (base[i].pagenos[j].isroman == FALSE)
- X fprintf(OutputFile, "%d\n", base[i].pagenos[j].number);
- X else {
- X fprintf(OutputFile, "{\\romannumeral %d}\n", base[i].pagenos[j].number);
- X }
- X } else if (base[i].pagenos[j].range) {
- X if (!prevrange) {
- X if (base[i].pagenos[j].isroman == FALSE)
- X fprintf(OutputFile, "%d--", base[i].pagenos[j].number);
- X else {
- X fprintf(OutputFile, "{\\romannumeral %d}--", base[i].pagenos[j].number);
- X }
- X }
- X } else {
- X if (base[i].pagenos[j].isroman == FALSE)
- X fprintf(OutputFile, "%d, ", base[i].pagenos[j].number);
- X else {
- X fprintf(OutputFile, "{\\romannumeral %d}, ", base[i].pagenos[j].number);
- X }
- X }
- X prevrange = base[i].pagenos[j].range;
- X }
- X if (prevrange)
- X fprintf(stderr, "%s: file %s, %s %s ends with a range\n", Whoami, IdxFileName, ItemRep[level - 1],
- X base[i].literal);
- X } else
- X fprintf(OutputFile, "\n");
- X if (base[i].subitem)
- X printindexentries(base[i].subitem, base[i].subitemcount, level + 1); /* recursion! */
- X }
- X}
- X
- Xint numericcompare(e1, e2)
- Xstruct PageNoTable *e1, *e2;
- X{
- X if ((e1->isroman == TRUE) && (e2->isroman == FALSE))
- X return -1;
- X if ((e1->isroman == FALSE) && (e2->isroman == TRUE))
- X return 1;
- X /* else either both roman or both integers */
- X if (e1->number == e2->number)
- X return 0;
- X else if (e1->number < e2->number)
- X return -1;
- X else
- X return 1;
- X}
- X
- Xint alphacompare(e1, e2)
- Xstruct IndexEntry *e1, *e2;
- X{
- X char s1[81], s2[81];
- X
- X strcpy(s1, e1->alphabetic), strcpy(s2, e2->alphabetic);
- X return(strcmp(string_downshift(s1), string_downshift(s2)));
- X}
- X
- Xint rmtoi (romanstr)
- Xchar *romanstr;
- X{
- X register char *p = romanstr;
- X register int w;
- X register int prevw = (-1);
- X register int result = 0;
- X int romanwt();
- X
- X while (*p) {
- X if ((w = romanwt(*p)) == (-1)) {
- X fprintf(stderr, "illegal char in roman string:'%c'\n", (*p));
- X return (-1);
- X } else {
- X if (prevw > 0) { /* check for subtractive
- X * notation */
- X if (w > prevw) { /* e.g., the case "ix" */
- X result += (w - prevw) - prevw;
- X } else
- X result += w;
- X } else {
- X result += w;
- X }
- X }
- X prevw = w;
- X p++;
- X }
- X return (result);
- X}
- X
- Xstatic int romanwt (c)
- Xregister char c;
- X{
- X static char romanlett[7] = {'m', 'd', 'c', 'l', 'x', 'v', 'i'};
- X static int weight[7] = {1000, 500, 100, 50, 10, 5, 1};
- X
- X register char *pt;
- X
- X if (isupper(c))
- X c = tolower(c);
- X pt = romanlett;
- X while (*pt) {
- X if (*pt == c) {
- X return (weight[(int) (pt - romanlett)]);
- X } else
- X pt++;
- X }
- X return (-1); /* roman letter not found */
- X}
- X
- !FaR!OuT!
- if [ ! -d indexsrc ]
- then
- mkdir indexsrc
- echo mkdir indexsrc
- fi
- echo x - indexsrc/indexlex.l
- sed -e 's/^X//' > indexsrc/indexlex.l << '!FaR!OuT!'
- X/* $Header */
- X/* Lex Lexical Analyzer for LaTeX index processor */
- X/* Roman numeral code written by John Renner (adobe!renner@decwrl.dec.com) */
- X%{
- X#undef input
- X#define input() (((yytchar=yysptr>yysbuf?U(*--yysptr):getc(InputFile)) \
- X ==10?(yylineno++,yytchar):yytchar)==EOF?0:yytchar)
- X%}
- Xletter [A-Za-z]
- Xinteger -?[0-9]{1,9}
- Xroman [mdclxvi]+
- Xwhitespace [ \t\n]
- X%%
- X\\indexentry {
- X LineNo = EndLineNo;
- X return(INDEXENTRY);
- X }
- X{roman} {
- X LineNo = EndLineNo;
- X strcpy(yylval.value, yytext);
- X return(ROMAN);
- X }
- X\\{letter}+ { /* Control word */
- X LineNo = EndLineNo;
- X strcpy(yylval.value, yytext);
- X return(CONTROLSEQUENCE);
- X }
- X\\[^{letter}] { /* Control symbol */
- X LineNo = EndLineNo;
- X strcpy(yylval.value, yytext);
- X return(CONTROLSEQUENCE);
- X }
- X\%.*\n LineNo = EndLineNo++; /* Comment. Don't pass to parser */
- X{integer} {
- X LineNo = EndLineNo;
- X strcpy(yylval.value, yytext);
- X return(INTEGER);
- X }
- X\{ |
- X\} |
- X\, {
- X LineNo = EndLineNo;
- X return(yytext[0]);
- X }
- X{whitespace}+ {
- X char *p; /* Utility variable */
- X
- X LineNo = EndLineNo;
- X for (p = yytext; *p; p++)
- X if (*p == '\n')
- X EndLineNo++;
- X strcpy(yylval.value, yytext);
- X return(WHITESPACE);
- X }
- X[^\\\{\}\%\, \t\n0-9]+ {
- X LineNo = EndLineNo;
- X strcpy(yylval.value, yytext);
- X return(STRING);
- X }
- X%%
- !FaR!OuT!
- if [ ! -d libglob ]
- then
- mkdir libglob
- echo mkdir libglob
- fi
- echo x - libglob/Makefile
- sed -e 's/^X//' > libglob/Makefile << '!FaR!OuT!'
- X# @(#)Makefile 1.1 (TRW) 1/14/86
- XCFLAGS = -O
- X
- X.c.o:
- X ${CC} ${CFLAGS} -c $*.c
- X -ld -x -r $*.o
- X mv a.out $*.o
- X
- Xall: libglob.a
- X
- Xlibglob.a: glob.o
- X ar cr libglob.a glob.o
- X ranlib libglob.a
- X chmod 644 libglob.a
- X
- Xinstall: all
- X
- Xclean:
- X rm -f *.o *.a
- X
- !FaR!OuT!
- if [ ! -d libglob ]
- then
- mkdir libglob
- echo mkdir libglob
- fi
- echo x - libglob/glob.c
- sed -e 's/^X//' > libglob/glob.c << '!FaR!OuT!'
- Xstatic char *trwsccs= "@(#)glob.c 1.1 (TRW) 1/14/86";
- X#include "glob.h"
- X
- X#define SLOP 5
- X#define MAX_SET 0177
- X
- X/* control codes for regular expression evaluation */
- X#define PATTERN_ANY '?'
- X#define PATTERN_CHARACTER 'X'
- X#define PATTERN_END '$'
- X#define PATTERN_SET '['
- X#define PATTERN_SET_MEMBER 'M'
- X#define PATTERN_SET_RANGE '-'
- X#define PATTERN_STAR '*'
- X
- X/*
- X * Examples (=> denotes `compiles into')
- X *
- X * a => Xa
- X * ? => ?
- X * [x0-9] => [^EMx-09 (^E is control-E)
- X * * => *
- X * END => $
- X *
- X * a?[x0-9]* => Xa?[^EMx-09*$
- X */
- X
- Xglob_compile (pattern, buffer)
- Xchar *pattern;
- Xchar *buffer; /* compiled pattern */
- X{
- X char *x; /* pointer into compiled pattern */
- X int c;
- X int result;
- X
- X if (pattern == 0 || pattern[0] == 0)
- X return(GLOB_PATTERN_EMPTY);
- X
- X x = buffer;
- X while (x < &buffer[GLOB_MAX_PATTERN - SLOP]) {
- X c = *pattern++;
- X if (c == 0) {
- X *x++ = PATTERN_END;
- X return(GLOB_OK);
- X }
- X
- X switch (c) {
- X case '?':
- X *x++ = PATTERN_ANY;
- X continue;
- X
- X case '[':
- X if ((result = compile_set(pattern, x, &buffer[GLOB_MAX_PATTERN - SLOP])) < 0)
- X return(result);
- X pattern += result + 1;
- X x += x[1] + 2;
- X continue;
- X
- X case '*':
- X *x++ = PATTERN_STAR;
- X continue;
- X
- X default:
- X *x++ = PATTERN_CHARACTER;
- X *x++ = c;
- X continue;
- X }
- X }
- X return(GLOB_PATTERN_TOO_BIG);
- X}
- X
- Xint glob_execute (pattern, s)
- Xchar *pattern; /* compiled pattern */
- Xchar *s; /* string to be matched against */
- X{
- X char *current;
- X int result;
- X
- X for (;;)
- X switch (*pattern++) {
- X case PATTERN_ANY:
- X if (*s++)
- X continue;
- X return(0);
- X
- X case PATTERN_CHARACTER:
- X if (*pattern++ == *s++)
- X continue;
- X return(0);
- X
- X case PATTERN_END:
- X return(*s == 0);
- X
- X case PATTERN_SET:
- X if ((result = in_set(pattern, *s++)) == 1) {
- X pattern += *pattern + 1;
- X continue;
- X }
- X return(result);
- X
- X case PATTERN_STAR:
- X current = s;
- X while (*s++)
- X continue;
- X do {
- X s--;
- X if (result = glob_execute(pattern, s))
- X return(result);
- X } while (s > current);
- X return(0);
- X
- X default:
- X return(GLOB_EXECUTION_ERROR);
- X }
- X}
- X
- Xint glob_match (pattern, s)
- Xchar *pattern;
- Xchar *s;
- X{
- X int result;
- X char buffer[GLOB_MAX_PATTERN];
- X
- X if ((result = glob_compile(pattern, buffer)) < 0)
- X return(result);
- X else
- X return(glob_execute(buffer, s));
- X}
- X
- X/* returns 1 if character c is member of set and 0 otherwise */
- Xstatic int in_set (set, c)
- Xchar *set; /* compiled set pattern */
- Xchar c;
- X{
- X int n;
- X
- X if (c == 0)
- X return(0);
- X n = *set++;
- X while (n > 0)
- X switch (*set++) {
- X case PATTERN_SET_MEMBER:
- X if (*set++ == c)
- X return(1);
- X n -= 2;
- X continue;
- X
- X case PATTERN_SET_RANGE:
- X if (*set++ <= c && c <= *set++)
- X return(1);
- X n -= 3;
- X continue;
- X
- X default:
- X return(GLOB_EXECUTION_ERROR);
- X }
- X return(0);
- X}
- X
- X#define IS_RANGE(s) (s[1] && s[2] && s[1] == '-' && s[2] != ']')
- X
- X/* compiles a set returning the number of pattern characters consumed */
- Xstatic int compile_set (pattern, x, limit)
- Xchar *pattern;
- Xchar *x;
- Xchar *limit;
- X{
- X char *slot; /* size of set goes here */
- X int size; /* number of bytes in compiled set */
- X char *start = pattern;
- X
- X if (*pattern == 0)
- X return(GLOB_BRACKET_MISSING);
- X
- X *x++ = PATTERN_SET;
- X slot = x++;
- X size = 0;
- X
- X if (IS_RANGE(pattern)) {
- X if (pattern[0] > pattern[2]) /* pattern[1] == '-' */
- X return(GLOB_RANGE_INVERTED);
- X *x++ = PATTERN_SET_RANGE;
- X *x++ = pattern[0];
- X *x++ = pattern[2];
- X pattern += 3;
- X size += 3;
- X } else {
- X *x++ = PATTERN_SET_MEMBER;
- X *x++ = *pattern++;
- X size += 2;
- X }
- X
- X while (*pattern != ']' && x < limit) {
- X if (*pattern == 0)
- X return(GLOB_BRACKET_MISSING);
- X if (IS_RANGE(pattern)) {
- X if (pattern[0] > pattern[2]) /* pattern[1] == '-' */
- X return(GLOB_RANGE_INVERTED);
- X *x++ = PATTERN_SET_RANGE;
- X *x++ = pattern[0];
- X *x++ = pattern[2];
- X pattern += 3;
- X size += 3;
- X } else {
- X *x++ = PATTERN_SET_MEMBER;
- X *x++ = *pattern++;
- X size += 2;
- X }
- X }
- X if (size > MAX_SET)
- X return(GLOB_SET_TOO_BIG);
- X *slot = size;
- X return(pattern - start);
- X}
- !FaR!OuT!
- if [ ! -d libglob ]
- then
- mkdir libglob
- echo mkdir libglob
- fi
- echo x - libglob/glob.h
- sed -e 's/^X//' > libglob/glob.h << '!FaR!OuT!'
- X/* @(#)glob.h 1.1 (TRW) 1/14/86 */
- X#define GLOB_MAX_PATTERN 1024
- X#define GLOB_OK 0
- X#define GLOB_PATTERN_TOO_BIG -1
- X#define GLOB_PATTERN_EMPTY -2
- X#define GLOB_BRACKET_MISSING -3
- X#define GLOB_RANGE_INVERTED -4
- X#define GLOB_SET_TOO_BIG -5
- X#define GLOB_EXECUTION_ERROR -6
- !FaR!OuT!
- exit
-