├── COPYING ├── Makefile.in ├── README ├── RELEASE_NOTES ├── configure ├── configure.in ├── dada.in ├── dadaprolog.ps ├── doc ├── Makefile.in ├── dada.ps └── dada.texi ├── include ├── format.pbi ├── html.pbi ├── plain.pbi ├── stdmap.pbi └── troff.pbi ├── inst.in ├── install-sh ├── man ├── dada.1 └── pb.1 ├── mkdirs.sh ├── regex ├── 00index.txt ├── COPYRIGHT ├── Makefile.in ├── Makefile.inc ├── WHATSNEW ├── cclass.h ├── cdefs.h ├── cname.h ├── engine.c ├── re_format.7 ├── regcomp.c ├── regerror.c ├── regex.3 ├── regex.h ├── regex2.h ├── regexec.c ├── regexp.h ├── regfree.c ├── sys │ └── cdefs.h └── utils.h ├── scripts ├── brag.pb ├── crackpot.pb ├── eqn.pb ├── exam.pb ├── legal.pb ├── loop.pb ├── manifesto.pb ├── pomo.pb ├── silly-word.pb ├── spout.pb └── test │ ├── bogus.pb │ ├── cascading.pb │ ├── codetest.pb │ ├── concattest.pb │ ├── digits.pb │ ├── inlinechoice.pb │ ├── maptest.pb │ ├── paramtest.pb │ ├── plus_star.pb │ ├── repeattest.pb │ ├── resource_decl.pb │ ├── test.pb │ ├── test2.pb │ └── xformtest.pb └── src ├── Makefile.in ├── check.c ├── check.h ├── config.h.in ├── dada.c ├── dada_pipe.c ├── dada_util.h ├── dict.c ├── dict.h ├── dstring.c ├── dstring.h ├── dump.c ├── emit_c.c ├── emit_ps.c ├── lexer.x ├── lextest.c ├── limits.h ├── machine.c ├── machine.h ├── map.c ├── map.h ├── parser.y ├── pb.c ├── pbc.c ├── ptrlist.c ├── ptrlist.h ├── resolve.c ├── resolve.h ├── resstack.c ├── resstack.h ├── rtn.c ├── rtn.h ├── strfunc.c ├── strfunc.h ├── transform.c ├── transform.h ├── variables.c ├── variables.h ├── wrap.c └── xmalloc.c /COPYING: -------------------------------------------------------------------------------- 1 | This software is copyrighted by Andrew C. Bulhak. 2 | 3 | The author hereby grants permission to use, copy, modify, distribute, 4 | and license this software and its documentation for any purpose, provided 5 | that existing copyright notices are retained in all copies and that this 6 | notice is included verbatim in any distributions. No written agreement, 7 | license, or royalty fee is required for any of the authorized uses. 8 | Modifications to this software may be copyrighted by their authors 9 | and need not follow the licensing terms described here, provided that 10 | the new terms are clearly indicated on the first page of each file where 11 | they apply. 12 | 13 | IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 14 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 | ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 16 | DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 17 | POSSIBILITY OF SUCH DAMAGE. 18 | 19 | THE AUTHORS AND DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, 20 | INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS SOFTWARE 22 | IS PROVIDED ON AN "AS IS" BASIS, AND THE AUTHORS AND DISTRIBUTORS HAVE 23 | NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 24 | MODIFICATIONS. 25 | 26 | 27 | This product includes software developed by the University of 28 | California, Berkeley and its contributors. 29 | -------------------------------------------------------------------------------- /Makefile.in: -------------------------------------------------------------------------------- 1 | # Main Dada Engine makefile 2 | 3 | # destination for compiled binaries 4 | 5 | @SET_MAKE@ 6 | 7 | prefix = @prefix@ 8 | exec_prefix = ${prefix} 9 | bindir = ${exec_prefix}/bin 10 | datadir = ${prefix}/lib 11 | infodir = ${prefix}/info 12 | mandir = ${prefix}/man 13 | 14 | SHELL = /bin/sh 15 | 16 | INSTALL_DIRS = ${bindir} ${datadir}/dada/include ${infodir} ${mandir}/man1 17 | 18 | cpp = @CPP_LOCATION@ 19 | 20 | INSTALL = @INSTALL@ 21 | 22 | all: dada 23 | @MAKE_REGEXP@ 24 | $(MAKE) -C src 25 | $(MAKE) -C doc 26 | 27 | dada: dada.in 28 | sed -e "s/@PBDIR@/`echo ${bindir} |sed -e s/\\\\//\\\\\\\\\\\\\\//g `/g" dada 29 | 30 | install: $(INSTALL_DIRS) \ 31 | $(bindir)/pb ${bindir}/dada ${infodir}/dada.info 32 | $(INSTALL) -m 0644 include/*.pbi ${datadir}/dada/include 33 | $(INSTALL) -m 0644 man/*.1 ${mandir}/man1 34 | @echo 'Installation complete.' 35 | 36 | ${bindir}/pb: src/pb 37 | $(INSTALL) -s src/pb ${bindir} 38 | ${bindir}/dada: dada 39 | $(INSTALL) dada ${bindir} 40 | ${infodir}/dada.info: doc/dada.info 41 | $(INSTALL) -m 0644 doc/dada.info ${infodir} 42 | 43 | # dependencies for installation 44 | 45 | $(INSTALL_DIRS): 46 | $(SHELL) mkdirs.sh $@ 47 | 48 | 49 | clean: 50 | rm -f *~ dada 51 | ( cd src ; make clean ) 52 | ( cd doc ; make clean ) 53 | ( cd regex ; make clean ) 54 | distclean: clean 55 | rm -f config.cache config.log config.status 56 | rm -f src/Makefile doc/Makefile regex/Makefile Makefile src/config.h inst 57 | 58 | 59 | dada.tar.gz: 60 | tar cvf dada.tar src/*.[chxy] src/config.h.in man scripts/*.pb Makefile.in */Makefile.in doc/*.texi include/*.pbi dadaprolog.ps dada.in README COPYING regex/*.[ch37] regex/sys/* regex/COPYRIGHT install-sh configure 61 | gzip -9c dada.tar >dada.tar.gz 62 | rm dada.tar 63 | 64 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | The Dada Engine Release 1.01 2 | ----------------------------- 3 | 4 | The Dada Engine is a system for the nondeterministic generation 5 | of ASCII data from grammars using recursive transition networks; or, 6 | in English, it is a system for generating random text using rules. 7 | Rules are specified in a language named pb, which looks a little like 8 | yacc, only a good deal more bogus. The language is documented in the 9 | Dada Engine manual which is supplied in Texinfo and PostScript formats. 10 | 11 | Release 1.01 is a bugfix release which fixes a problem with regular 12 | expression substitutions in 1.0. Nothing else is changed. 13 | 14 | Compiling and installing 15 | ------------------------ 16 | 17 | Firstly, run the shell script named "configure" in the Dada Engine 18 | distribution directory. This will check the characteristics of your 19 | system and (hopefully) set up the makefiles and headers in a way that 20 | will work. configure, by default, sets the installation directories 21 | in which the Dada Engine will be installed to /usr/local; if you 22 | wish to install the Dada Engine elsewhere, you can specify a different 23 | location by running configure with the "--prefix=pathname" argument, 24 | i.e., "./configure --prefix=$HOME" will install the system in your 25 | home directory. 26 | 27 | Then run "make" in the distribution directory; this will compile the 28 | Dada Engine. Afterwards, for it to properly work, you must install it 29 | by running "make install". 30 | 31 | Sample scripts 32 | -------------- 33 | 34 | Several sample scripts are provided in the `scripts' subdirectory. 35 | These include: 36 | 37 | brag.pb* A SubGenius brag generator 38 | crackpot.pb A crackpot rant generator 39 | eqn.pb A generator of bogus equations (in LaTeX format) 40 | exam.pb A script to generate intimidating-looking but bogus 41 | examination questions. (unfinished) 42 | legal.pb* A script to generate legalese. 43 | loop.pb* A script that produces itself as output 44 | manifesto.pb A manifesto generator 45 | pomo.pb The Postmodernism Generator; now outputs in any 46 | format supported by the format library 47 | silly-word.pb A silly word generator 48 | spout.pb* The SubGenius Profunditied Generation Matrix 49 | 50 | 51 | Acknowledgements 52 | ---------------- 53 | 54 | I am grateful to Mitchell Porter for testing the language and coding 55 | several of the example scripts, to the Department of Computer Science 56 | at Monash University for facilities and support, to Jamie Cameron for 57 | his part in the conspiracy to develop this system and to Brandon Long 58 | and kristin buxton for their help with getting the Dada Engine to work 59 | with Solaris 2.x. 60 | 61 | Andrew C. Bulhak 62 | acb@dev.null.org 63 | 45 Discord 3162 64 | -------------------------------------------------------------------------------- /RELEASE_NOTES: -------------------------------------------------------------------------------- 1 | This is the 1.01 release of the Dada Engine. 2 | 3 | 1.01 is a bugfix release, which fixes a problem with regular 4 | expression substitutions in 1.0. 5 | 6 | This program has been gotten to compile successfully on the following 7 | platforms: Linux, MIPS ULTRIX, Irix 5.3, Solaris 2.x and Digital UNIX 3.2. 8 | Your mileage may vary. 9 | 10 | Under some systems, such as ULTRIX and Solaris, the installation script 11 | ("make install") may not work properly. If this is the case, run the 12 | "inst" script that is created, with "sh inst". 13 | 14 | If you have problems making it, try using GNU make. SGI's make, for 15 | example, had some problems. 16 | 17 | acb 18 | Chaoflux 3162 19 | -------------------------------------------------------------------------------- /configure.in: -------------------------------------------------------------------------------- 1 | dnl Process this file with autoconf to produce a configure script. 2 | AC_INIT(src/check.c) 3 | 4 | AC_CONFIG_HEADER(src/config.h) 5 | 6 | dnl Checks for programs. 7 | AC_PROG_LEX 8 | AC_PROG_CC 9 | AC_PROG_INSTALL 10 | AC_PROG_MAKE_SET 11 | AC_PROG_YACC 12 | AC_PROG_RANLIB 13 | 14 | dnl Find the C preprocessor, wherever it may be on this system 15 | AC_MSG_CHECKING(where to find the C preprocessor) 16 | if test -x /lib/cpp 17 | then 18 | CPP_LOCATION="/lib/cpp" 19 | AC_MSG_RESULT(/lib/cpp) 20 | else 21 | if test -x /usr/ccs/lib/cpp 22 | then 23 | CPP_LOCATION="/usr/ccs/lib/cpp" 24 | AC_MSG_RESULT(/usr/ccs/lib/cpp) 25 | else 26 | dnl some sort of smart /usr/lib/gcc-lib/** check would be nice 27 | if test -d /usr/lib/gcc-lib 28 | then 29 | foo=`find /usr/lib/gcc-lib -type f -name cpp -print |head -1` 30 | if -n "$foo" 31 | then 32 | CPP_LOCATION="$foo" 33 | AC_MSG_RESULT("$foo") 34 | else 35 | dnl punt 36 | CPP_LOCATION="cpp" 37 | AC_MSG_RESULT("unknown. you\'re on your own...") 38 | fi 39 | fi 40 | 41 | fi 42 | fi 43 | 44 | dnl Checks for libraries. 45 | 46 | dnl kludge for Solaris 2.x 47 | 48 | AC_MSG_CHECKING(for /usr/ucblib) 49 | if test -d /usr/ucblib 50 | then 51 | LIBS="-L/usr/ucblib $LIBS" 52 | AC_MSG_RESULT(yes) 53 | else 54 | AC_MSG_RESULT(no) 55 | fi 56 | 57 | dnl Checks for header files. 58 | AC_HEADER_STDC 59 | AC_CHECK_HEADERS(unistd.h) 60 | 61 | dnl Checks for typedefs, structures, and compiler characteristics. 62 | AC_C_CONST 63 | AC_C_INLINE 64 | 65 | dnl Checks for library functions. 66 | AC_FUNC_ALLOCA 67 | AC_CHECK_LIB(ucb, random) 68 | AC_CHECK_FUNCS(regcomp strcspn strdup) 69 | AC_CHECK_FUNC(regcomp, HAVE_REGCOMP=1, [ 70 | MAKE_REGEXP='$(MAKE) -C regex' 71 | REGEXP_LIB='../regex/libregex.a' 72 | REGEXP_INCLUDE='-I../regex' 73 | ]) 74 | 75 | AC_SUBST(MAKE_REGEXP) 76 | AC_SUBST(REGEXP_LIB) 77 | AC_SUBST(REGEXP_INCLUDE) 78 | AC_SUBST(CPP_LOCATION) 79 | 80 | AC_OUTPUT(Makefile doc/Makefile src/Makefile regex/Makefile inst) 81 | -------------------------------------------------------------------------------- /dada.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # User interface/wrapper for the Dada Engine 3 | # Author: acb 4 | # Commenced: 14-7-1995 5 | 6 | PBDIR="@PBDIR@" 7 | DADAROOT="@DADAROOT@" 8 | CPP="@_CPP@" 9 | 10 | #CPP="/lib/cpp" 11 | #CPPARGS="-lang-c++" 12 | FILES="" 13 | #PB="`dirname $0`/pb" 14 | #INCLUDE="-I`dirname $0`/include -I$DADAROOT/include" 15 | PB="${PBDIR}/pb" 16 | INCLUDE="-I${DADAROOT}/include" 17 | 18 | while test $# -gt 0 19 | do 20 | case $1 in 21 | -D*) CPPARGS="$1 $CPPARGS";; 22 | -o) PBARGS="$PBARGS $1 $2"; shift;; 23 | -p) PBARGS="$PBARGS $1";; 24 | -r) PBARGS="$PBARGS $1 $2"; shift;; 25 | -s) PBARGS="$PBARGS $1 $2"; shift;; 26 | -w) PBARGS="$PBARGS $1 $2"; shift;; 27 | *) CPPARGS="$CPPARGS $1";; 28 | esac 29 | shift 30 | done 31 | 32 | ($CPP $INCLUDE $CPPARGS 2>/dev/null) | $PB $PBARGS 33 | -------------------------------------------------------------------------------- /dadaprolog.ps: -------------------------------------------------------------------------------- 1 | %!PS 2 | %%Creator: acb 3 | %%CreationDate: July 11, 1995 4 | 5 | %% This is code for resolving recursive grammars in PostScript. 6 | %% This code is part of the Dada Engine and copyright of Andrew C. Bulhak 7 | %% You may use, distribute and modify this code in any way provided that 8 | %% this copyright notice remains intact. 9 | 10 | /bd {bind def} bind def 11 | 12 | % choose an element from an array at random 13 | % syntax: [array] choose elem 14 | 15 | /choose { 16 | dup length rand exch mod get 17 | } bd 18 | 19 | % concatenate an array of strings into a string 20 | % [array] strcat (str) 21 | /strcat { 22 | dup 23 | } bd 24 | 25 | % syntax: name value conddef - 26 | 27 | /conddef { 28 | 1 index where { pop pop pop } { def } ifelse 29 | } bd 30 | 31 | % (str) n repeat [array] 32 | 33 | /rep { 34 | dup 1 1 3 -1 roll { 35 | pop exch dup 3 -1 roll 36 | } for 37 | [ exch 1 add 1 roll ] exch pop 38 | } bd 39 | 40 | % syntax: string star [strings] 41 | 42 | /star { 43 | 0 { rand 5 mod 1 le {exit} if 1 add } loop 44 | rep 45 | % dup array exch 1 1 3 -1 roll 46 | % { 1 sub 1 index exch 3 index put } for 47 | % exch pop 48 | } bd 49 | 50 | /plus { 51 | 1 { rand 5 mod 1 le {exit} if 1 add } loop 52 | rep 53 | % dup array exch 1 1 3 -1 roll 54 | % { 1 sub 1 index exch 3 index put } for 55 | % exch pop 56 | } bd 57 | 58 | %% End of Dada Engine prologue 59 | -------------------------------------------------------------------------------- /doc/Makefile.in: -------------------------------------------------------------------------------- 1 | all: dada.info 2 | 3 | dada.info: dada.texi 4 | makeinfo dada.texi 5 | 6 | clean: 7 | rm -f *~ *.info 8 | -------------------------------------------------------------------------------- /include/format.pbi: -------------------------------------------------------------------------------- 1 | // format.pbi acb 65 Afm 3161 2 | // Main Dada Engine include file, for selecting the output format from 3 | // preprocessor defines 4 | 5 | #ifdef HTML 6 | #include 7 | #else 8 | #if defined(NROFF) || defined(TROFF) || defined(DITROFF) 9 | #include 10 | #else 11 | #include 12 | #endif 13 | 14 | #endif -------------------------------------------------------------------------------- /include/html.pbi: -------------------------------------------------------------------------------- 1 | // html.pbi acb 13-7-1995 2 | // Definitions for HTML output for the Dada Engine. 3 | 4 | #ifndef __HTML_PBI 5 | #define __HTML_PBI 6 | 7 | #include 8 | 9 | // PROLOGUE: format-specific prologue 10 | 11 | %resource PROLOGUE: { HTML_section_num=0; HTML_footnote_num=0 ; 12 | HTML_footnotes="" 13 | } "" {HTML_BODY=""}; 14 | 15 | // EPILOGUE: format-specific epilogue 16 | 17 | %resource EPILOGUE: "
\n" $HTML_footnotes ""; 18 | 19 | // BODY: called when body text is to start 20 | 21 | %resource BODY: $HTML_BODY {HTML_BODY=""}; 22 | 23 | // TITLE(t): generates code at start of output for title 24 | 25 | TITLE(t): "" t "" $HTML_BODY { HTML_BODY="" } "

" t "

" "\n" ; 26 | 27 | // AUTHOR(au): generates a formatted author name; usually used after the 28 | // title 29 | 30 | AUTHOR(au): "

" au "

\n" ; 31 | 32 | // AUTHOR_INST(auth inst): generates a formatted author name and institution; 33 | // usually used after the title. 34 | 35 | AUTHOR_INST(auth inst): "

" auth "
\n" inst "

\n"; 36 | 37 | // SECTION(title): generates a numbered section title. 38 | 39 | SECTION(title): { HTML_section_num=HTML_section_num+1 } "

" 40 | $HTML_section_num ". " title>upcase-first "

\n" ; 41 | 42 | // FOOTNOTE(text): generates a numbered footnote 43 | 44 | FOOTNOTE(text): ?tx=text // parameters can't be used in inline code as such 45 | { HTML_footnote_num=HTML_footnote_num+1 } "[" $HTML_footnote_num "] " { // append the text to the accumulating footnotes 47 | HTML_footnotes = HTML_footnotes + " " 48 | + HTML_footnote_num + ". " + tx + "

\n" 49 | } 50 | ; 51 | 52 | // BRK: generates a line break 53 | 54 | %resource BRK: "
\n"; 55 | 56 | // PBRK: generates a paragraph break 57 | 58 | %resource PBRK: "

\n"; 59 | 60 | 61 | // ************************************************************************ 62 | // 63 | // Text styles and the like 64 | // 65 | // ************************************************************************ 66 | 67 | 68 | BOLD(foo): "" foo ""; 69 | ITALIC(foo): "" foo ""; 70 | 71 | 72 | #endif 73 | -------------------------------------------------------------------------------- /include/plain.pbi: -------------------------------------------------------------------------------- 1 | // plain.pbi acb 13-7-1995 2 | // Definitions for plain-text output for the Dada Engine. 3 | 4 | #ifndef __PLAIN_PBI 5 | #define __PLAIN_PBI 6 | 7 | #include 8 | 9 | // PROLOGUE: format-specific prologue 10 | 11 | %resource PROLOGUE: {PLAIN_section_num=0; PLAIN_footnote_num=0; 12 | PLAIN_footnotes="" } ""; 13 | 14 | // EPILOGUE: format-specific epilogue 15 | 16 | %resource EPILOGUE: "\n\n----\n" $PLAIN_footnotes; 17 | 18 | // BODY: called when body text is to start 19 | 20 | %resource BODY: ""; 21 | 22 | // TITLE(t): generates code at start of output for title 23 | 24 | TITLE(t): t "\n\n" ; 25 | 26 | // AUTHOR(au): generates a formatted author name; usually used after the 27 | // title 28 | 29 | AUTHOR(au): au "\n\n" ; 30 | 31 | // AUTHOR_INST(auth inst): generates a formatted author name and institution; 32 | // usually used after the title. 33 | 34 | AUTHOR_INST(auth inst): auth "\n" inst "\n\n"; 35 | 36 | // SECTION(title): generates a numbered section title. 37 | 38 | SECTION(title): { PLAIN_section_num = PLAIN_section_num+1 } "\n\n" 39 | $PLAIN_section_num ". " title>upcase-first "\n"; 40 | 41 | // FOOTNOTE(text): generates a numbered footnote 42 | 43 | FOOTNOTE(text): ?tx=text // the inline-code parameter bug^H^H^Hfeature. 44 | { PLAIN_footnote_num=PLAIN_footnote_num+1 } " [" $PLAIN_footnote_num "] " 45 | { // append the text to the accumulating footnotes 46 | PLAIN_footnotes = PLAIN_footnotes + PLAIN_footnote_num+". "+tx+"\n" 47 | } 48 | ; 49 | 50 | // BRK: generates a line break 51 | 52 | %resource BRK: "\n"; 53 | 54 | // PBRK: generates a paragraph break 55 | 56 | %resource PBRK: "\n\n"; 57 | 58 | // ************************************************************************ 59 | // 60 | // Text styles and the like 61 | // 62 | // ************************************************************************ 63 | 64 | // here, text styles aren't really used. 65 | 66 | BOLD(foo): foo ; 67 | ITALIC(foo): foo ; 68 | 69 | #endif 70 | -------------------------------------------------------------------------------- /include/stdmap.pbi: -------------------------------------------------------------------------------- 1 | // stdmap.pbi acb Chs 49 3162 2 | // Commonly used mappings and transformations 3 | 4 | #ifndef __STDMAP_PBI 5 | #define __STDMAP_PBI 6 | 7 | 8 | // upcase: convert an entire string to uppercase 9 | 10 | %trans upcase: 11 | ".*": u ; 12 | ; 13 | 14 | 15 | // upcase-first: convert the first character of a string to its upper-case 16 | // equivalent 17 | 18 | %trans upcase-first: 19 | ".*": 0 u ; 20 | ; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /include/troff.pbi: -------------------------------------------------------------------------------- 1 | // troff.pbi acb 49 Chs 3162 2 | // Definitions for UNIX (n|t|dit)roff typesetting system output 3 | // (with the ms macro package) 4 | 5 | #ifndef __TROFF_PBI 6 | #define __TROFF_PBI 7 | 8 | #include 9 | 10 | // PROLOGUE: format-specific prologue 11 | // we don't want an abstract in our output 12 | 13 | %resource PROLOGUE: { 14 | TROFF_footnote_num = 0 15 | } ".ds ABSTRACT \n" ; 16 | 17 | // EPILOGUE: format-specific epilogue 18 | 19 | %resource EPILOGUE: "" ; 20 | 21 | // BODY: called when body text is to start 22 | 23 | %resource BODY: "\n.AB\n.AE\n" 24 | #ifdef TROFF_2COLUMN 25 | ".2C\n" 26 | #endif 27 | ; 28 | 29 | // TITLE(t): generates code at start of output for title 30 | 31 | TITLE(t): "\n.TL\n" title>upcase-first ; 32 | 33 | // AUTHOR(au): generates a formatted author name; usually used after the 34 | // title 35 | 36 | AUTHOR(au): "\n.AU\n" au "\n" ; 37 | 38 | // AUTHOR_INST(auth inst): generates a formatted author name and institution; 39 | // usually used after the title. 40 | 41 | AUTHOR_INST(auth inst): "\n.AU\n" auth "\n.AI\n" inst"\n" ; 42 | 43 | // SECTION(title): generates a numbered section title. 44 | 45 | SECTION(title): "\n.NH\n" title>upcase-first "\n.PP" ; 46 | 47 | // FOOTNOTE(text): generates a numbered footnote 48 | 49 | FOOTNOTE(text): { TROFF_footnote_num = TROFF_footnote_num+1 } 50 | "\\*{" $TROFF_footnote_num "\\*}\n.FS\n" $TROFF_footnote_num ". " text 51 | "\n.FE\n" ; 52 | 53 | // BRK: generates a line break 54 | 55 | %resource BRK: "\n.br\n"; 56 | 57 | // PBRK: generates a paragraph break 58 | 59 | %resource PBRK: "\n.PP\n" ; 60 | 61 | // ************************************************************************ 62 | // 63 | // Text styles and the like 64 | // 65 | // ************************************************************************ 66 | 67 | BOLD(foo): "\\fB" foo "\\fR" ; 68 | ITALIC(foo): "\\fI" foo "\\fR" ; 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /inst.in: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # this is required because install-sh doesn't run properly from a 4 | # makefile on some systems (such as some Solaris 2.x systems)... :-/ 5 | 6 | INSTALL="@INSTALL@" 7 | prefix=@prefix@ 8 | exec_prefix=$prefix 9 | bindir=${prefix}/bin 10 | datadir=${prefix}/lib 11 | infodir=${prefix}/info 12 | mandir=${prefix}/man 13 | 14 | echo $INSTALL -s src/pb $bindir 15 | $INSTALL -s src/pb $bindir 16 | echo $INSTALL dada $bindir 17 | $INSTALL dada $bindir 18 | echo $INSTALL -m 0644 doc/dada.info $infodir 19 | $INSTALL -m 0644 doc/dada.info $infodir 20 | echo $INSTALL -m 0644 include/*.pbi ${datadir}/dada/include 21 | $INSTALL -m 0644 include/*.pbi ${datadir}/dada/include 22 | echo $INSTALL -m 0644 man/*.1 ${mandir}/man1 23 | $INSTALL -m 0644 man/*.1 ${mandir}/man1 24 | echo "Installation completed." 25 | -------------------------------------------------------------------------------- /install-sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | # 3 | # install - install a program, script, or datafile 4 | # This comes from X11R5. 5 | # 6 | # Calling this script install-sh is preferred over install.sh, to prevent 7 | # `make' implicit rules from creating a file called install from it 8 | # when there is no Makefile. 9 | # 10 | # This script is compatible with the BSD install script, but was written 11 | # from scratch. 12 | # 13 | 14 | 15 | # set DOITPROG to echo to test this script 16 | 17 | # Don't use :- since 4.3BSD and earlier shells don't like it. 18 | doit="${DOITPROG-}" 19 | 20 | 21 | # put in absolute paths if you don't have them in your path; or use env. vars. 22 | 23 | mvprog="${MVPROG-mv}" 24 | cpprog="${CPPROG-cp}" 25 | chmodprog="${CHMODPROG-chmod}" 26 | chownprog="${CHOWNPROG-chown}" 27 | chgrpprog="${CHGRPPROG-chgrp}" 28 | stripprog="${STRIPPROG-strip}" 29 | rmprog="${RMPROG-rm}" 30 | mkdirprog="${MKDIRPROG-mkdir}" 31 | 32 | tranformbasename="" 33 | transform_arg="" 34 | instcmd="$mvprog" 35 | chmodcmd="$chmodprog 0755" 36 | chowncmd="" 37 | chgrpcmd="" 38 | stripcmd="" 39 | rmcmd="$rmprog -f" 40 | mvcmd="$mvprog" 41 | src="" 42 | dst="" 43 | dir_arg="" 44 | 45 | while [ x"$1" != x ]; do 46 | case $1 in 47 | -c) instcmd="$cpprog" 48 | shift 49 | continue;; 50 | 51 | -d) dir_arg=true 52 | shift 53 | continue;; 54 | 55 | -m) chmodcmd="$chmodprog $2" 56 | shift 57 | shift 58 | continue;; 59 | 60 | -o) chowncmd="$chownprog $2" 61 | shift 62 | shift 63 | continue;; 64 | 65 | -g) chgrpcmd="$chgrpprog $2" 66 | shift 67 | shift 68 | continue;; 69 | 70 | -s) stripcmd="$stripprog" 71 | shift 72 | continue;; 73 | 74 | -t=*) transformarg=`echo $1 | sed 's/-t=//'` 75 | shift 76 | continue;; 77 | 78 | -b=*) transformbasename=`echo $1 | sed 's/-b=//'` 79 | shift 80 | continue;; 81 | 82 | *) if [ x"$src" = x ] 83 | then 84 | src=$1 85 | else 86 | # this colon is to work around a 386BSD /bin/sh bug 87 | : 88 | dst=$1 89 | fi 90 | shift 91 | continue;; 92 | esac 93 | done 94 | 95 | if [ x"$src" = x ] 96 | then 97 | echo "install: no input file specified" 98 | exit 1 99 | else 100 | true 101 | fi 102 | 103 | if [ x"$dir_arg" != x ]; then 104 | dst=$src 105 | src="" 106 | 107 | if [ -d $dst ]; then 108 | instcmd=: 109 | else 110 | instcmd=mkdir 111 | fi 112 | else 113 | 114 | # Waiting for this to be detected by the "$instcmd $src $dsttmp" command 115 | # might cause directories to be created, which would be especially bad 116 | # if $src (and thus $dsttmp) contains '*'. 117 | 118 | if [ -f $src -o -d $src ] 119 | then 120 | true 121 | else 122 | echo "install: $src does not exist" 123 | exit 1 124 | fi 125 | 126 | if [ x"$dst" = x ] 127 | then 128 | echo "install: no destination specified" 129 | exit 1 130 | else 131 | true 132 | fi 133 | 134 | # If destination is a directory, append the input filename; if your system 135 | # does not like double slashes in filenames, you may need to add some logic 136 | 137 | if [ -d $dst ] 138 | then 139 | dst="$dst"/`basename $src` 140 | else 141 | true 142 | fi 143 | fi 144 | 145 | ## this sed command emulates the dirname command 146 | dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` 147 | 148 | # Make sure that the destination directory exists. 149 | # this part is taken from Noah Friedman's mkinstalldirs script 150 | 151 | # Skip lots of stat calls in the usual case. 152 | if [ ! -d "$dstdir" ]; then 153 | defaultIFS=' 154 | ' 155 | IFS="${IFS-${defaultIFS}}" 156 | 157 | oIFS="${IFS}" 158 | # Some sh's can't handle IFS=/ for some reason. 159 | IFS='%' 160 | set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` 161 | IFS="${oIFS}" 162 | 163 | pathcomp='' 164 | 165 | while [ $# -ne 0 ] ; do 166 | pathcomp="${pathcomp}${1}" 167 | shift 168 | 169 | if [ ! -d "${pathcomp}" ] ; 170 | then 171 | $mkdirprog "${pathcomp}" 172 | else 173 | true 174 | fi 175 | 176 | pathcomp="${pathcomp}/" 177 | done 178 | fi 179 | 180 | if [ x"$dir_arg" != x ] 181 | then 182 | $doit $instcmd $dst && 183 | 184 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else true ; fi && 185 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else true ; fi && 186 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else true ; fi && 187 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else true ; fi 188 | else 189 | 190 | # If we're going to rename the final executable, determine the name now. 191 | 192 | if [ x"$transformarg" = x ] 193 | then 194 | dstfile=`basename $dst` 195 | else 196 | dstfile=`basename $dst $transformbasename | 197 | sed $transformarg`$transformbasename 198 | fi 199 | 200 | # don't allow the sed command to completely eliminate the filename 201 | 202 | if [ x"$dstfile" = x ] 203 | then 204 | dstfile=`basename $dst` 205 | else 206 | true 207 | fi 208 | 209 | # Make a temp file name in the proper directory. 210 | 211 | dsttmp=$dstdir/#inst.$$# 212 | 213 | # Move or copy the file name to the temp name 214 | 215 | $doit $instcmd $src $dsttmp && 216 | 217 | trap "rm -f ${dsttmp}" 0 && 218 | 219 | # and set any options; do chmod last to preserve setuid bits 220 | 221 | # If any of these fail, we abort the whole thing. If we want to 222 | # ignore errors from any of these, just make sure not to ignore 223 | # errors from the above "$doit $instcmd $src $dsttmp" command. 224 | 225 | if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else true;fi && 226 | if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else true;fi && 227 | if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else true;fi && 228 | if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else true;fi && 229 | 230 | # Now rename the file to the real destination. 231 | 232 | $doit $rmcmd -f $dstdir/$dstfile && 233 | $doit $mvcmd $dsttmp $dstdir/$dstfile 234 | 235 | fi && 236 | 237 | 238 | exit 0 239 | -------------------------------------------------------------------------------- /man/dada.1: -------------------------------------------------------------------------------- 1 | .TH dada 1 "16 Jul 1995" "Emperor Norton Utilities" 2 | .SH NAME 3 | dada \- front end for the Dada Engine. 4 | .SH SYNOPSIS 5 | .B dada 6 | [\-Ddefinition [\-Ddefinition ...]] [\-o outfile] [\-s startsym] 7 | .I filename 8 | .SH DESCRIPTION 9 | .B The Dada Engine 10 | is a programmable system for generating random text from a grammar. 11 | Grammars are written in the 12 | .B pb 13 | language, which has a syntax vaguely similar to Backus-Naur Format (BNF), 14 | production systems or yacc(1). 15 | .PP 16 | .I dada 17 | is a shell script which serves as the preferred user interface to the Dada 18 | Engine. It is called with the name of a pb script and possibly some options. 19 | When called, it invokes the C preprocessor, 20 | .I cpp(1), 21 | on the script provided and any define options on the command line. The 22 | output of the preprocessor is piped into the pb interpreter, 23 | .I pb(1), along with other arguments. 24 | .PP 25 | .SH OPTIONS 26 | .TP 27 | .B -D\fIdef\fR 28 | Defines the preprocessor symbol \fIdef\fR. 29 | .TP 30 | .B -D\fIdef=value\fR 31 | Defines the preprocessor symbol \fIdef\fR to be equal to \fIvalue\fR. 32 | .TP 33 | .B -o \fIfilename\fR 34 | Redirects output to the file thus named; if not supplied, output will go to 35 | the standard output. 36 | .TP 37 | .B -r \fIrandomseed\fR 38 | Defines a seed for the random number generator used to select options. 39 | If this is not specified, the random number generator is seeded from the 40 | current system time. 41 | .TP 42 | .B -s \fIstartsym\fR 43 | Defines the 44 | .I "start symbol," 45 | the name of the rule which is initially evaluated. If not specified, this 46 | defaults to the first rule in the script. 47 | .PP 48 | .SH SEE ALSO 49 | cpp(1), sh(1), 50 | .I The pb Language 51 | .SH AUTHOR 52 | Andrew C. Bulhak 53 | 54 | -------------------------------------------------------------------------------- /man/pb.1: -------------------------------------------------------------------------------- 1 | .TH pb 1 "4 Chaos 3162" "Emperor Norton Utilities" 2 | .SH NAME 3 | pb \- recursive random text generation engine 4 | .SH SYNOPSIS 5 | .B pb 6 | [\-d] [\-i] [\-r 7 | .I "randomseed" 8 | ] [\-s 9 | .I "start symbol" 10 | ] [\-v] <\fIfilename\fR 11 | .SH DESCRIPTION 12 | .B pb 13 | is a programmable system for generating random text from a grammar. 14 | Grammars are stored in user-specified text files, in a format similar to 15 | Backus-Naur Format (BNF) or production systems. The language used to define 16 | .I pb 17 | grammars is described in the Texinfo documentation provided. 18 | .PP 19 | .I pb 20 | is invoked as a pipe, and reads its grammar from the standard input. 21 | .PP 22 | If the command line contains the 23 | .B \-d 24 | flag, pb will dump the internal representation of the grammar to the 25 | standard output. 26 | .PP 27 | If the command line contains the 28 | .B \-i 29 | flag, pb will not evaluate the grammar, but merely read it. This option is 30 | useful with the \-d flag. 31 | .PP 32 | By default, pb seeds its random number generator with the current system time. 33 | An alternative seed (either an integer or a string) may be specified with the 34 | .B \-r 35 | switch. 36 | .PP 37 | By default, pb will evaluate the first rule defined in a grammar; this rule 38 | is referred to as the 39 | .I "start symbol" . 40 | An alternate start symbol may be specified with the 41 | .B -s 42 | switch. 43 | .PP 44 | The 45 | .B -v 46 | option causes pb to output state information, and is primarily useful for 47 | debugging. 48 | .PP 49 | .SH BUGS 50 | Transformations are still somewhat flaky, and may not always give the desired 51 | results. 52 | .SH COPYING 53 | The author hereby grants permission to use, copy, modify, distribute, 54 | and license this software and its documentation for any purpose, provided 55 | that existing copyright notices are retained in all copies and that this 56 | notice is included verbatim in any distributions. No written agreement, 57 | license, or royalty fee is required for any of the authorized uses. 58 | Modifications to this software may be copyrighted by their authors 59 | and need not follow the licensing terms described here, provided that 60 | the new terms are clearly indicated on the first page of each file where 61 | they apply. 62 | .PP 63 | IN NO EVENT SHALL THE AUTHORS OR DISTRIBUTORS BE LIABLE TO ANY PARTY 64 | FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 65 | ARISING OUT OF THE USE OF THIS SOFTWARE, ITS DOCUMENTATION, OR ANY 66 | DERIVATIVES THEREOF, EVEN IF THE AUTHORS HAVE BEEN ADVISED OF THE 67 | POSSIBILITY OF SUCH DAMAGE. 68 | .SH AUTHOR 69 | Andrew C. Bulhak 70 | -------------------------------------------------------------------------------- /mkdirs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # mkinstalldirs --- make directory hierarchy 3 | # Author: Noah Friedman 4 | # Created: 1993-05-16 5 | # Last modified: 1994-03-25 6 | # Public domain 7 | # 8 | # $Header: /usr2/foxharp/src/pgf/vile/RCS/mkdirs.sh,v 1.2 1994/07/11 22:56:20 pgf Exp $ 9 | # 10 | 11 | errstatus=0 12 | 13 | for file in ${1+"$@"} ; do 14 | set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` 15 | shift 16 | 17 | pathcomp= 18 | for d in ${1+"$@"} ; do 19 | pathcomp="$pathcomp$d" 20 | case "$pathcomp" in 21 | -* ) pathcomp=./$pathcomp ;; 22 | esac 23 | 24 | if test ! -d "$pathcomp"; then 25 | echo "mkdir $pathcomp" 1>&2 26 | mkdir "$pathcomp" || errstatus=$? 27 | fi 28 | 29 | pathcomp="$pathcomp/" 30 | done 31 | done 32 | 33 | exit $errstatus 34 | 35 | # mkinstalldirs ends here 36 | -------------------------------------------------------------------------------- /regex/00index.txt: -------------------------------------------------------------------------------- 1 | 00index.txt 390 2 | COPYRIGHT 2894 3 | Makefile.inc 283 4 | WHATSNEW 5335 5 | cclass.h 2933 6 | cname.h 3881 7 | engine.c 28860 8 | re_format.7 11738 9 | regcomp.c 41850 10 | regerror.c 5560 11 | regex.3 16762 12 | regex2.h 7399 13 | regexec.c 6356 14 | regfree.c 2879 15 | utils.h 2483 16 | -------------------------------------------------------------------------------- /regex/COPYRIGHT: -------------------------------------------------------------------------------- 1 | Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved. 2 | This software is not subject to any license of the American Telephone 3 | and Telegraph Company or of the Regents of the University of California. 4 | 5 | Permission is granted to anyone to use this software for any purpose on 6 | any computer system, and to alter it and redistribute it, subject 7 | to the following restrictions: 8 | 9 | 1. The author is not responsible for the consequences of use of this 10 | software, no matter how awful, even if they arise from flaws in it. 11 | 12 | 2. The origin of this software must not be misrepresented, either by 13 | explicit claim or by omission. Since few users ever read sources, 14 | credits must appear in the documentation. 15 | 16 | 3. Altered versions must be plainly marked as such, and must not be 17 | misrepresented as being the original software. Since few users 18 | ever read sources, credits must appear in the documentation. 19 | 20 | 4. This notice may not be removed or altered. 21 | 22 | =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 23 | /*- 24 | * Copyright (c) 1994 25 | * The Regents of the University of California. All rights reserved. 26 | * 27 | * Redistribution and use in source and binary forms, with or without 28 | * modification, are permitted provided that the following conditions 29 | * are met: 30 | * 1. Redistributions of source code must retain the above copyright 31 | * notice, this list of conditions and the following disclaimer. 32 | * 2. Redistributions in binary form must reproduce the above copyright 33 | * notice, this list of conditions and the following disclaimer in the 34 | * documentation and/or other materials provided with the distribution. 35 | * 3. All advertising materials mentioning features or use of this software 36 | * must display the following acknowledgement: 37 | * This product includes software developed by the University of 38 | * California, Berkeley and its contributors. 39 | * 4. Neither the name of the University nor the names of its contributors 40 | * may be used to endorse or promote products derived from this software 41 | * without specific prior written permission. 42 | * 43 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 44 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 45 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 46 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 47 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 48 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 49 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 50 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 51 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 52 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 53 | * SUCH DAMAGE. 54 | * 55 | * @(#)COPYRIGHT 8.1 (Berkeley) 3/16/94 56 | */ 57 | -------------------------------------------------------------------------------- /regex/Makefile.in: -------------------------------------------------------------------------------- 1 | RANLIB = @RANLIB@ 2 | CC = @CC@ 3 | 4 | CFLAGS=-DPOSIX_MISTAKE 5 | 6 | SRCS= regcomp.c regerror.c regexec.c regfree.c 7 | OBJS= regcomp.o regerror.o regexec.o regfree.o 8 | 9 | all: libregex.a 10 | 11 | libregex.a: $(OBJS) 12 | ar ruv libregex.a $(OBJS) 13 | $(RANLIB) libregex.a 14 | 15 | engine.o: engine.c 16 | regcomp.o: regcomp.c utils.h regex2.h cclass.h cname.h 17 | regerror.o: regerror.c utils.h 18 | regexec.o: regexec.c utils.h regex2.h engine.c 19 | regfree.o: regfree.c utils.h regex2.h 20 | 21 | clean: 22 | rm -f *.[ao] 23 | 24 | -------------------------------------------------------------------------------- /regex/Makefile.inc: -------------------------------------------------------------------------------- 1 | # @(#)Makefile.inc 8.1 (Berkeley) 6/4/93 2 | 3 | # regex sources 4 | .PATH: ${.CURDIR}/regex 5 | 6 | CFLAGS+=-DPOSIX_MISTAKE 7 | 8 | SRCS+= regcomp.c regerror.c regexec.c regfree.c 9 | 10 | MAN3+= regex.0 11 | MAN7+= re_format.0 12 | 13 | MLINKS+=regex.3 regcomp.3 regex.3 regexec.3 regex.3 regerror.3 14 | MLINKS+=regexec.3 regfree.3 15 | -------------------------------------------------------------------------------- /regex/WHATSNEW: -------------------------------------------------------------------------------- 1 | # @(#)WHATSNEW 8.3 (Berkeley) 3/18/94 2 | 3 | New in alpha3.4: The complex bug alluded to below has been fixed (in a 4 | slightly kludgey temporary way that may hurt efficiency a bit; this is 5 | another "get it out the door for 4.4" release). The tests at the end of 6 | the tests file have accordingly been uncommented. The primary sign of 7 | the bug was that something like a?b matching ab matched b rather than ab. 8 | (The bug was essentially specific to this exact situation, else it would 9 | have shown up earlier.) 10 | 11 | New in alpha3.3: The definition of word boundaries has been altered 12 | slightly, to more closely match the usual programming notion that "_" 13 | is an alphabetic. Stuff used for pre-ANSI systems is now in a subdir, 14 | and the makefile no longer alludes to it in mysterious ways. The 15 | makefile has generally been cleaned up some. Fixes have been made 16 | (again!) so that the regression test will run without -DREDEBUG, at 17 | the cost of weaker checking. A workaround for a bug in some folks' 18 | has been added. And some more things have been added to 19 | tests, including a couple right at the end which are commented out 20 | because the code currently flunks them (complex bug; fix coming). 21 | Plus the usual minor cleanup. 22 | 23 | New in alpha3.2: Assorted bits of cleanup and portability improvement 24 | (the development base is now a BSDI system using GCC instead of an ancient 25 | Sun system, and the newer compiler exposed some glitches). Fix for a 26 | serious bug that affected REs using many [] (including REG_ICASE REs 27 | because of the way they are implemented), *sometimes*, depending on 28 | memory-allocation patterns. The header-file prototypes no longer name 29 | the parameters, avoiding possible name conflicts. The possibility that 30 | some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is 31 | now handled gracefully. "uchar" is no longer used as an internal type 32 | name (too many people have the same idea). Still the same old lousy 33 | performance, alas. 34 | 35 | New in alpha3.1: Basically nothing, this release is just a bookkeeping 36 | convenience. Stay tuned. 37 | 38 | New in alpha3.0: Performance is no better, alas, but some fixes have been 39 | made and some functionality has been added. (This is basically the "get 40 | it out the door in time for 4.4" release.) One bug fix: regfree() didn't 41 | free the main internal structure (how embarrassing). It is now possible 42 | to put NULs in either the RE or the target string, using (resp.) a new 43 | REG_PEND flag and the old REG_STARTEND flag. The REG_NOSPEC flag to 44 | regcomp() makes all characters ordinary, so you can match a literal 45 | string easily (this will become more useful when performance improves!). 46 | There are now primitives to match beginnings and ends of words, although 47 | the syntax is disgusting and so is the implementation. The REG_ATOI 48 | debugging interface has changed a bit. And there has been considerable 49 | internal cleanup of various kinds. 50 | 51 | New in alpha2.3: Split change list out of README, and moved flags notes 52 | into Makefile. Macro-ized the name of regex(7) in regex(3), since it has 53 | to change for 4.4BSD. Cleanup work in engine.c, and some new regression 54 | tests to catch tricky cases thereof. 55 | 56 | New in alpha2.2: Out-of-date manpages updated. Regerror() acquires two 57 | small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges 58 | in my own test program and might be useful to others for similar purposes. 59 | The regression test will now compile (and run) without REDEBUG. The 60 | BRE \$ bug is fixed. Most uses of "uchar" are gone; it's all chars now. 61 | Char/uchar parameters are now written int/unsigned, to avoid possible 62 | portability problems with unpromoted parameters. Some unsigned casts have 63 | been introduced to minimize portability problems with shifting into sign 64 | bits. 65 | 66 | New in alpha2.1: Lots of little stuff, cleanup and fixes. The one big 67 | thing is that regex.h is now generated, using mkh, rather than being 68 | supplied in the distribution; due to circularities in dependencies, 69 | you have to build regex.h explicitly by "make h". The two known bugs 70 | have been fixed (and the regression test now checks for them), as has a 71 | problem with assertions not being suppressed in the absence of REDEBUG. 72 | No performance work yet. 73 | 74 | New in alpha2: Backslash-anything is an ordinary character, not an 75 | error (except, of course, for the handful of backslashed metacharacters 76 | in BREs), which should reduce script breakage. The regression test 77 | checks *where* null strings are supposed to match, and has generally 78 | been tightened up somewhat. Small bug fixes in parameter passing (not 79 | harmful, but technically errors) and some other areas. Debugging 80 | invoked by defining REDEBUG rather than not defining NDEBUG. 81 | 82 | New in alpha+3: full prototyping for internal routines, using a little 83 | helper program, mkh, which extracts prototypes given in stylized comments. 84 | More minor cleanup. Buglet fix: it's CHAR_BIT, not CHAR_BITS. Simple 85 | pre-screening of input when a literal string is known to be part of the 86 | RE; this does wonders for performance. 87 | 88 | New in alpha+2: minor bits of cleanup. Notably, the number "32" for the 89 | word width isn't hardwired into regexec.c any more, the public header 90 | file prototypes the functions if __STDC__ is defined, and some small typos 91 | in the manpages have been fixed. 92 | 93 | New in alpha+1: improvements to the manual pages, and an important 94 | extension, the REG_STARTEND option to regexec(). 95 | -------------------------------------------------------------------------------- /regex/cclass.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)cclass.h 8.3 (Berkeley) 3/20/94 38 | */ 39 | 40 | /* character-class table */ 41 | static struct cclass { 42 | char *name; 43 | char *chars; 44 | char *multis; 45 | } cclasses[] = { 46 | "alnum", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ 47 | 0123456789", "", 48 | "alpha", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", 49 | "", 50 | "blank", " \t", "", 51 | "cntrl", "\007\b\t\n\v\f\r\1\2\3\4\5\6\16\17\20\21\22\23\24\ 52 | \25\26\27\30\31\32\33\34\35\36\37\177", "", 53 | "digit", "0123456789", "", 54 | "graph", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ 55 | 0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", 56 | "", 57 | "lower", "abcdefghijklmnopqrstuvwxyz", 58 | "", 59 | "print", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz\ 60 | 0123456789!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ", 61 | "", 62 | "punct", "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~", 63 | "", 64 | "space", "\t\n\v\f\r ", "", 65 | "upper", "ABCDEFGHIJKLMNOPQRSTUVWXYZ", 66 | "", 67 | "xdigit", "0123456789ABCDEFabcdef", 68 | "", 69 | NULL, 0, "" 70 | }; 71 | -------------------------------------------------------------------------------- /regex/cdefs.h: -------------------------------------------------------------------------------- 1 | /* cdefs.h acb 66 Afm 3161 2 | * replace sys/cdefs.h for non-POSIX systems. 4.4BSD's regex needs this. 3 | */ 4 | 5 | #ifndef __CDEFS_H 6 | #define __CDEFS_H 7 | 8 | #define __BEGIN_DECLS 9 | #define __END_DECLS 10 | 11 | #if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) 12 | 13 | #ifndef __P 14 | #define __P(a) a 15 | #endif 16 | 17 | #else 18 | 19 | #ifndef __P 20 | #define __P(a) 21 | #endif 22 | 23 | 24 | #endif 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /regex/cname.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)cname.h 8.3 (Berkeley) 3/20/94 38 | */ 39 | 40 | /* character-name table */ 41 | static struct cname { 42 | char *name; 43 | char code; 44 | } cnames[] = { 45 | "NUL", '\0', 46 | "SOH", '\001', 47 | "STX", '\002', 48 | "ETX", '\003', 49 | "EOT", '\004', 50 | "ENQ", '\005', 51 | "ACK", '\006', 52 | "BEL", '\007', 53 | "alert", '\007', 54 | "BS", '\010', 55 | "backspace", '\b', 56 | "HT", '\011', 57 | "tab", '\t', 58 | "LF", '\012', 59 | "newline", '\n', 60 | "VT", '\013', 61 | "vertical-tab", '\v', 62 | "FF", '\014', 63 | "form-feed", '\f', 64 | "CR", '\015', 65 | "carriage-return", '\r', 66 | "SO", '\016', 67 | "SI", '\017', 68 | "DLE", '\020', 69 | "DC1", '\021', 70 | "DC2", '\022', 71 | "DC3", '\023', 72 | "DC4", '\024', 73 | "NAK", '\025', 74 | "SYN", '\026', 75 | "ETB", '\027', 76 | "CAN", '\030', 77 | "EM", '\031', 78 | "SUB", '\032', 79 | "ESC", '\033', 80 | "IS4", '\034', 81 | "FS", '\034', 82 | "IS3", '\035', 83 | "GS", '\035', 84 | "IS2", '\036', 85 | "RS", '\036', 86 | "IS1", '\037', 87 | "US", '\037', 88 | "space", ' ', 89 | "exclamation-mark", '!', 90 | "quotation-mark", '"', 91 | "number-sign", '#', 92 | "dollar-sign", '$', 93 | "percent-sign", '%', 94 | "ampersand", '&', 95 | "apostrophe", '\'', 96 | "left-parenthesis", '(', 97 | "right-parenthesis", ')', 98 | "asterisk", '*', 99 | "plus-sign", '+', 100 | "comma", ',', 101 | "hyphen", '-', 102 | "hyphen-minus", '-', 103 | "period", '.', 104 | "full-stop", '.', 105 | "slash", '/', 106 | "solidus", '/', 107 | "zero", '0', 108 | "one", '1', 109 | "two", '2', 110 | "three", '3', 111 | "four", '4', 112 | "five", '5', 113 | "six", '6', 114 | "seven", '7', 115 | "eight", '8', 116 | "nine", '9', 117 | "colon", ':', 118 | "semicolon", ';', 119 | "less-than-sign", '<', 120 | "equals-sign", '=', 121 | "greater-than-sign", '>', 122 | "question-mark", '?', 123 | "commercial-at", '@', 124 | "left-square-bracket", '[', 125 | "backslash", '\\', 126 | "reverse-solidus", '\\', 127 | "right-square-bracket", ']', 128 | "circumflex", '^', 129 | "circumflex-accent", '^', 130 | "underscore", '_', 131 | "low-line", '_', 132 | "grave-accent", '`', 133 | "left-brace", '{', 134 | "left-curly-bracket", '{', 135 | "vertical-line", '|', 136 | "right-brace", '}', 137 | "right-curly-bracket", '}', 138 | "tilde", '~', 139 | "DEL", '\177', 140 | NULL, 0, 141 | }; 142 | -------------------------------------------------------------------------------- /regex/regerror.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regerror.c 8.4 (Berkeley) 3/20/94 38 | */ 39 | 40 | #if defined(LIBC_SCCS) && !defined(lint) 41 | static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94"; 42 | #endif /* LIBC_SCCS and not lint */ 43 | 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | #include 50 | /*#include changed by acb */ 51 | #include "regex.h" 52 | 53 | #include "utils.h" 54 | 55 | /* ========= begin header generated by ./mkh ========= */ 56 | #ifdef __cplusplus 57 | extern "C" { 58 | #endif 59 | 60 | /* === regerror.c === */ 61 | static char *regatoi __P((const regex_t *preg, char *localbuf)); 62 | 63 | #ifdef __cplusplus 64 | } 65 | #endif 66 | /* ========= end header generated by ./mkh ========= */ 67 | /* 68 | = #define REG_NOMATCH 1 69 | = #define REG_BADPAT 2 70 | = #define REG_ECOLLATE 3 71 | = #define REG_ECTYPE 4 72 | = #define REG_EESCAPE 5 73 | = #define REG_ESUBREG 6 74 | = #define REG_EBRACK 7 75 | = #define REG_EPAREN 8 76 | = #define REG_EBRACE 9 77 | = #define REG_BADBR 10 78 | = #define REG_ERANGE 11 79 | = #define REG_ESPACE 12 80 | = #define REG_BADRPT 13 81 | = #define REG_EMPTY 14 82 | = #define REG_ASSERT 15 83 | = #define REG_INVARG 16 84 | = #define REG_ATOI 255 // convert name to number (!) 85 | = #define REG_ITOA 0400 // convert number to name (!) 86 | */ 87 | static struct rerr { 88 | int code; 89 | char *name; 90 | char *explain; 91 | } rerrs[] = { 92 | REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match", 93 | REG_BADPAT, "REG_BADPAT", "invalid regular expression", 94 | REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element", 95 | REG_ECTYPE, "REG_ECTYPE", "invalid character class", 96 | REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)", 97 | REG_ESUBREG, "REG_ESUBREG", "invalid backreference number", 98 | REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced", 99 | REG_EPAREN, "REG_EPAREN", "parentheses not balanced", 100 | REG_EBRACE, "REG_EBRACE", "braces not balanced", 101 | REG_BADBR, "REG_BADBR", "invalid repetition count(s)", 102 | REG_ERANGE, "REG_ERANGE", "invalid character range", 103 | REG_ESPACE, "REG_ESPACE", "out of memory", 104 | REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid", 105 | REG_EMPTY, "REG_EMPTY", "empty (sub)expression", 106 | REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug", 107 | REG_INVARG, "REG_INVARG", "invalid argument to regex routine", 108 | 0, "", "*** unknown regexp error code ***", 109 | }; 110 | 111 | /* 112 | - regerror - the interface to error numbers 113 | = extern size_t regerror(int, const regex_t *, char *, size_t); 114 | */ 115 | /* ARGSUSED */ 116 | size_t 117 | regerror(errcode, preg, errbuf, errbuf_size) 118 | int errcode; 119 | const regex_t *preg; 120 | char *errbuf; 121 | size_t errbuf_size; 122 | { 123 | register struct rerr *r; 124 | register size_t len; 125 | register int target = errcode &~ REG_ITOA; 126 | register char *s; 127 | char convbuf[50]; 128 | 129 | if (errcode == REG_ATOI) 130 | s = regatoi(preg, convbuf); 131 | else { 132 | for (r = rerrs; r->code != 0; r++) 133 | if (r->code == target) 134 | break; 135 | 136 | if (errcode®_ITOA) { 137 | if (r->code != 0) 138 | (void) strcpy(convbuf, r->name); 139 | else 140 | sprintf(convbuf, "REG_0x%x", target); 141 | assert(strlen(convbuf) < sizeof(convbuf)); 142 | s = convbuf; 143 | } else 144 | s = r->explain; 145 | } 146 | 147 | len = strlen(s) + 1; 148 | if (errbuf_size > 0) { 149 | if (errbuf_size > len) 150 | (void) strcpy(errbuf, s); 151 | else { 152 | (void) strncpy(errbuf, s, errbuf_size-1); 153 | errbuf[errbuf_size-1] = '\0'; 154 | } 155 | } 156 | 157 | return(len); 158 | } 159 | 160 | /* 161 | - regatoi - internal routine to implement REG_ATOI 162 | == static char *regatoi(const regex_t *preg, char *localbuf); 163 | */ 164 | static char * 165 | regatoi(preg, localbuf) 166 | const regex_t *preg; 167 | char *localbuf; 168 | { 169 | register struct rerr *r; 170 | register size_t siz; 171 | register char *p; 172 | 173 | for (r = rerrs; r->code != 0; r++) 174 | if (strcmp(r->name, preg->re_endp) == 0) 175 | break; 176 | if (r->code == 0) 177 | return("0"); 178 | 179 | sprintf(localbuf, "%d", r->code); 180 | return(localbuf); 181 | } 182 | -------------------------------------------------------------------------------- /regex/regex.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992 Henry Spencer. 3 | * Copyright (c) 1992, 1993 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer of the University of Toronto. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regex.h 8.2 (Berkeley) 1/3/94 38 | */ 39 | 40 | #ifndef _REGEX_H_ 41 | #define _REGEX_H_ 42 | 43 | #include 44 | #include "cdefs.h" 45 | 46 | /* types */ 47 | typedef off_t regoff_t; 48 | 49 | typedef struct { 50 | int re_magic; 51 | size_t re_nsub; /* number of parenthesized subexpressions */ 52 | __const char *re_endp; /* end pointer for REG_PEND */ 53 | struct re_guts *re_g; /* none of your business :-) */ 54 | } regex_t; 55 | 56 | typedef struct { 57 | regoff_t rm_so; /* start of match */ 58 | regoff_t rm_eo; /* end of match */ 59 | } regmatch_t; 60 | 61 | /* regcomp() flags */ 62 | #define REG_BASIC 0000 63 | #define REG_EXTENDED 0001 64 | #define REG_ICASE 0002 65 | #define REG_NOSUB 0004 66 | #define REG_NEWLINE 0010 67 | #define REG_NOSPEC 0020 68 | #define REG_PEND 0040 69 | #define REG_DUMP 0200 70 | 71 | /* regerror() flags */ 72 | #define REG_NOMATCH 1 73 | #define REG_BADPAT 2 74 | #define REG_ECOLLATE 3 75 | #define REG_ECTYPE 4 76 | #define REG_EESCAPE 5 77 | #define REG_ESUBREG 6 78 | #define REG_EBRACK 7 79 | #define REG_EPAREN 8 80 | #define REG_EBRACE 9 81 | #define REG_BADBR 10 82 | #define REG_ERANGE 11 83 | #define REG_ESPACE 12 84 | #define REG_BADRPT 13 85 | #define REG_EMPTY 14 86 | #define REG_ASSERT 15 87 | #define REG_INVARG 16 88 | #define REG_ATOI 255 /* convert name to number (!) */ 89 | #define REG_ITOA 0400 /* convert number to name (!) */ 90 | 91 | /* regexec() flags */ 92 | #define REG_NOTBOL 00001 93 | #define REG_NOTEOL 00002 94 | #define REG_STARTEND 00004 95 | #define REG_TRACE 00400 /* tracing of execution */ 96 | #define REG_LARGE 01000 /* force large representation */ 97 | #define REG_BACKR 02000 /* force use of backref code */ 98 | 99 | __BEGIN_DECLS 100 | int regcomp __P((regex_t *, const char *, int)); 101 | size_t regerror __P((int, const regex_t *, char *, size_t)); 102 | int regexec __P((const regex_t *, 103 | const char *, size_t, regmatch_t [], int)); 104 | void regfree __P((regex_t *)); 105 | __END_DECLS 106 | 107 | #endif /* !_REGEX_H_ */ 108 | -------------------------------------------------------------------------------- /regex/regex2.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regex2.h 8.4 (Berkeley) 3/20/94 38 | */ 39 | 40 | /* 41 | * First, the stuff that ends up in the outside-world include file 42 | = typedef off_t regoff_t; 43 | = typedef struct { 44 | = int re_magic; 45 | = size_t re_nsub; // number of parenthesized subexpressions 46 | = const char *re_endp; // end pointer for REG_PEND 47 | = struct re_guts *re_g; // none of your business :-) 48 | = } regex_t; 49 | = typedef struct { 50 | = regoff_t rm_so; // start of match 51 | = regoff_t rm_eo; // end of match 52 | = } regmatch_t; 53 | */ 54 | /* 55 | * internals of regex_t 56 | */ 57 | #define MAGIC1 ((('r'^0200)<<8) | 'e') 58 | 59 | /* 60 | * The internal representation is a *strip*, a sequence of 61 | * operators ending with an endmarker. (Some terminology etc. is a 62 | * historical relic of earlier versions which used multiple strips.) 63 | * Certain oddities in the representation are there to permit running 64 | * the machinery backwards; in particular, any deviation from sequential 65 | * flow must be marked at both its source and its destination. Some 66 | * fine points: 67 | * 68 | * - OPLUS_ and O_PLUS are *inside* the loop they create. 69 | * - OQUEST_ and O_QUEST are *outside* the bypass they create. 70 | * - OCH_ and O_CH are *outside* the multi-way branch they create, while 71 | * OOR1 and OOR2 are respectively the end and the beginning of one of 72 | * the branches. Note that there is an implicit OOR2 following OCH_ 73 | * and an implicit OOR1 preceding O_CH. 74 | * 75 | * In state representations, an operator's bit is on to signify a state 76 | * immediately *preceding* "execution" of that operator. 77 | */ 78 | typedef unsigned long sop; /* strip operator */ 79 | typedef long sopno; 80 | #define OPRMASK 0xf8000000 81 | #define OPDMASK 0x07ffffff 82 | #define OPSHIFT ((unsigned)27) 83 | #define OP(n) ((n)&OPRMASK) 84 | #define OPND(n) ((n)&OPDMASK) 85 | #define SOP(op, opnd) ((op)|(opnd)) 86 | /* operators meaning operand */ 87 | /* (back, fwd are offsets) */ 88 | #define OEND (1< uch [csetsize] */ 123 | uch mask; /* bit within array */ 124 | uch hash; /* hash code */ 125 | size_t smultis; 126 | char *multis; /* -> char[smulti] ab\0cd\0ef\0\0 */ 127 | } cset; 128 | /* note that CHadd and CHsub are unsafe, and CHIN doesn't yield 0/1 */ 129 | #define CHadd(cs, c) ((cs)->ptr[(uch)(c)] |= (cs)->mask, (cs)->hash += (c)) 130 | #define CHsub(cs, c) ((cs)->ptr[(uch)(c)] &= ~(cs)->mask, (cs)->hash -= (c)) 131 | #define CHIN(cs, c) ((cs)->ptr[(uch)(c)] & (cs)->mask) 132 | #define MCadd(p, cs, cp) mcadd(p, cs, cp) /* regcomp() internal fns */ 133 | #define MCsub(p, cs, cp) mcsub(p, cs, cp) 134 | #define MCin(p, cs, cp) mcin(p, cs, cp) 135 | 136 | /* stuff for character categories */ 137 | typedef unsigned char cat_t; 138 | 139 | /* 140 | * main compiled-expression structure 141 | */ 142 | struct re_guts { 143 | int magic; 144 | # define MAGIC2 ((('R'^0200)<<8)|'E') 145 | sop *strip; /* malloced area for strip */ 146 | int csetsize; /* number of bits in a cset vector */ 147 | int ncsets; /* number of csets in use */ 148 | cset *sets; /* -> cset [ncsets] */ 149 | uch *setbits; /* -> uch[csetsize][ncsets/CHAR_BIT] */ 150 | int cflags; /* copy of regcomp() cflags argument */ 151 | sopno nstates; /* = number of sops */ 152 | sopno firststate; /* the initial OEND (normally 0) */ 153 | sopno laststate; /* the final OEND */ 154 | int iflags; /* internal flags */ 155 | # define USEBOL 01 /* used ^ */ 156 | # define USEEOL 02 /* used $ */ 157 | # define BAD 04 /* something wrong */ 158 | int nbol; /* number of ^ used */ 159 | int neol; /* number of $ used */ 160 | int ncategories; /* how many character categories */ 161 | cat_t *categories; /* ->catspace[-CHAR_MIN] */ 162 | char *must; /* match must contain this string */ 163 | int mlen; /* length of must */ 164 | size_t nsub; /* copy of re_nsub */ 165 | int backrefs; /* does it use back references? */ 166 | sopno nplus; /* how deep does it nest +s? */ 167 | /* catspace must be last */ 168 | cat_t catspace[1]; /* actually [NC] */ 169 | }; 170 | 171 | /* misc utilities */ 172 | #define OUT (CHAR_MAX+1) /* a non-character value */ 173 | #define ISWORD(c) (isalnum(c) || (c) == '_') 174 | -------------------------------------------------------------------------------- /regex/regexec.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regexec.c 8.3 (Berkeley) 3/20/94 38 | */ 39 | 40 | #if defined(LIBC_SCCS) && !defined(lint) 41 | static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94"; 42 | #endif /* LIBC_SCCS and not lint */ 43 | 44 | /* 45 | * the outer shell of regexec() 46 | * 47 | * This file includes engine.c *twice*, after muchos fiddling with the 48 | * macros that code uses. This lets the same code operate on two different 49 | * representations for state sets. 50 | */ 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | /* #include */ 58 | #include "regex.h" 59 | 60 | #include "utils.h" 61 | #include "regex2.h" 62 | 63 | static int nope = 0; /* for use in asserts; shuts lint up */ 64 | 65 | /* macros for manipulating states, small version */ 66 | #define states long 67 | #define states1 states /* for later use in regexec() decision */ 68 | #define CLEAR(v) ((v) = 0) 69 | #define SET0(v, n) ((v) &= ~(1 << (n))) 70 | #define SET1(v, n) ((v) |= 1 << (n)) 71 | #define ISSET(v, n) ((v) & (1 << (n))) 72 | #define ASSIGN(d, s) ((d) = (s)) 73 | #define EQ(a, b) ((a) == (b)) 74 | #define STATEVARS int dummy /* dummy version */ 75 | #define STATESETUP(m, n) /* nothing */ 76 | #define STATETEARDOWN(m) /* nothing */ 77 | #define SETUP(v) ((v) = 0) 78 | #define onestate int 79 | #define INIT(o, n) ((o) = (unsigned)1 << (n)) 80 | #define INC(o) ((o) <<= 1) 81 | #define ISSTATEIN(v, o) ((v) & (o)) 82 | /* some abbreviations; note that some of these know variable names! */ 83 | /* do "if I'm here, I can also be there" etc without branches */ 84 | #define FWD(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) << (n)) 85 | #define BACK(dst, src, n) ((dst) |= ((unsigned)(src)&(here)) >> (n)) 86 | #define ISSETBACK(v, n) ((v) & ((unsigned)here >> (n))) 87 | /* function names */ 88 | #define SNAMES /* engine.c looks after details */ 89 | 90 | #include "engine.c" 91 | 92 | /* now undo things */ 93 | #undef states 94 | #undef CLEAR 95 | #undef SET0 96 | #undef SET1 97 | #undef ISSET 98 | #undef ASSIGN 99 | #undef EQ 100 | #undef STATEVARS 101 | #undef STATESETUP 102 | #undef STATETEARDOWN 103 | #undef SETUP 104 | #undef onestate 105 | #undef INIT 106 | #undef INC 107 | #undef ISSTATEIN 108 | #undef FWD 109 | #undef BACK 110 | #undef ISSETBACK 111 | #undef SNAMES 112 | 113 | /* macros for manipulating states, large version */ 114 | #define states char * 115 | #define CLEAR(v) memset(v, 0, m->g->nstates) 116 | #define SET0(v, n) ((v)[n] = 0) 117 | #define SET1(v, n) ((v)[n] = 1) 118 | #define ISSET(v, n) ((v)[n]) 119 | #define ASSIGN(d, s) memcpy(d, s, m->g->nstates) 120 | #define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0) 121 | #define STATEVARS int vn; char *space 122 | #define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \ 123 | if ((m)->space == NULL) return(REG_ESPACE); \ 124 | (m)->vn = 0; } 125 | #define STATETEARDOWN(m) { free((m)->space); } 126 | #define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates]) 127 | #define onestate int 128 | #define INIT(o, n) ((o) = (n)) 129 | #define INC(o) ((o)++) 130 | #define ISSTATEIN(v, o) ((v)[o]) 131 | /* some abbreviations; note that some of these know variable names! */ 132 | /* do "if I'm here, I can also be there" etc without branches */ 133 | #define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here]) 134 | #define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here]) 135 | #define ISSETBACK(v, n) ((v)[here - (n)]) 136 | /* function names */ 137 | #define LNAMES /* flag */ 138 | 139 | #include "engine.c" 140 | 141 | /* 142 | - regexec - interface for matching 143 | = extern int regexec(const regex_t *, const char *, size_t, \ 144 | = regmatch_t [], int); 145 | = #define REG_NOTBOL 00001 146 | = #define REG_NOTEOL 00002 147 | = #define REG_STARTEND 00004 148 | = #define REG_TRACE 00400 // tracing of execution 149 | = #define REG_LARGE 01000 // force large representation 150 | = #define REG_BACKR 02000 // force use of backref code 151 | * 152 | * We put this here so we can exploit knowledge of the state representation 153 | * when choosing which matcher to call. Also, by this point the matchers 154 | * have been prototyped. 155 | */ 156 | int /* 0 success, REG_NOMATCH failure */ 157 | regexec(preg, string, nmatch, pmatch, eflags) 158 | const regex_t *preg; 159 | const char *string; 160 | size_t nmatch; 161 | regmatch_t pmatch[]; 162 | int eflags; 163 | { 164 | register struct re_guts *g = preg->re_g; 165 | #ifdef REDEBUG 166 | # define GOODFLAGS(f) (f) 167 | #else 168 | # define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND)) 169 | #endif 170 | 171 | if (preg->re_magic != MAGIC1 || g->magic != MAGIC2) 172 | return(REG_BADPAT); 173 | assert(!(g->iflags&BAD)); 174 | if (g->iflags&BAD) /* backstop for no-debug case */ 175 | return(REG_BADPAT); 176 | eflags = GOODFLAGS(eflags); 177 | 178 | if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags®_LARGE)) 179 | return(smatcher(g, (char *)string, nmatch, pmatch, eflags)); 180 | else 181 | return(lmatcher(g, (char *)string, nmatch, pmatch, eflags)); 182 | } 183 | -------------------------------------------------------------------------------- /regex/regexp.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1986 by University of Toronto. 3 | * Copyright (c) 1989, 1993 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley 7 | * by Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regexp.h 8.1 (Berkeley) 6/2/93 38 | */ 39 | 40 | #ifndef _REGEXP_H_ 41 | #define _REGEXP_H_ 42 | 43 | /* 44 | * Definitions etc. for regexp(3) routines. 45 | * 46 | * Caveat: this is V8 regexp(3) [actually, a reimplementation thereof], 47 | * not the System V one. 48 | */ 49 | #define NSUBEXP 10 50 | typedef struct regexp { 51 | char *startp[NSUBEXP]; 52 | char *endp[NSUBEXP]; 53 | char regstart; /* Internal use only. */ 54 | char reganch; /* Internal use only. */ 55 | char *regmust; /* Internal use only. */ 56 | int regmlen; /* Internal use only. */ 57 | char program[1]; /* Unwarranted chumminess with compiler. */ 58 | } regexp; 59 | 60 | #include 61 | 62 | __BEGIN_DECLS 63 | regexp *regcomp __P((const char *)); 64 | int regexec __P((const regexp *, const char *)); 65 | void regsub __P((const regexp *, const char *, char *)); 66 | void regerror __P((const char *)); 67 | __END_DECLS 68 | 69 | #endif /* !_REGEXP_H_ */ 70 | -------------------------------------------------------------------------------- /regex/regfree.c: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)regfree.c 8.3 (Berkeley) 3/20/94 38 | */ 39 | 40 | #if defined(LIBC_SCCS) && !defined(lint) 41 | static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94"; 42 | #endif /* LIBC_SCCS and not lint */ 43 | 44 | #include 45 | #include 46 | #include 47 | /*#include */ 48 | #include "regex.h" 49 | 50 | #include "utils.h" 51 | #include "regex2.h" 52 | 53 | /* 54 | - regfree - free everything 55 | = extern void regfree(regex_t *); 56 | */ 57 | void 58 | regfree(preg) 59 | regex_t *preg; 60 | { 61 | register struct re_guts *g; 62 | 63 | if (preg->re_magic != MAGIC1) /* oops */ 64 | return; /* nice to complain, but hard */ 65 | 66 | g = preg->re_g; 67 | if (g == NULL || g->magic != MAGIC2) /* oops again */ 68 | return; 69 | preg->re_magic = 0; /* mark it invalid */ 70 | g->magic = 0; /* mark it invalid */ 71 | 72 | if (g->strip != NULL) 73 | free((char *)g->strip); 74 | if (g->sets != NULL) 75 | free((char *)g->sets); 76 | if (g->setbits != NULL) 77 | free((char *)g->setbits); 78 | if (g->must != NULL) 79 | free(g->must); 80 | free((char *)g); 81 | } 82 | -------------------------------------------------------------------------------- /regex/sys/cdefs.h: -------------------------------------------------------------------------------- 1 | /* cdefs.h acb 66 Afm 3161 2 | * replace sys/cdefs.h for non-POSIX systems. 4.4BSD's regex needs this. 3 | */ 4 | 5 | #ifndef __CDEFS_H 6 | #define __CDEFS_H 7 | 8 | #if defined(__STDC__) || defined(__GNUC__) || defined(__cplusplus) 9 | 10 | #ifndef __P 11 | #define __P(a) a 12 | #endif 13 | 14 | #else 15 | 16 | #ifndef __P 17 | #define __P(a) 18 | #endif 19 | 20 | 21 | #endif 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /regex/utils.h: -------------------------------------------------------------------------------- 1 | /*- 2 | * Copyright (c) 1992, 1993, 1994 Henry Spencer. 3 | * Copyright (c) 1992, 1993, 1994 4 | * The Regents of the University of California. All rights reserved. 5 | * 6 | * This code is derived from software contributed to Berkeley by 7 | * Henry Spencer. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 1. Redistributions of source code must retain the above copyright 13 | * notice, this list of conditions and the following disclaimer. 14 | * 2. Redistributions in binary form must reproduce the above copyright 15 | * notice, this list of conditions and the following disclaimer in the 16 | * documentation and/or other materials provided with the distribution. 17 | * 3. All advertising materials mentioning features or use of this software 18 | * must display the following acknowledgement: 19 | * This product includes software developed by the University of 20 | * California, Berkeley and its contributors. 21 | * 4. Neither the name of the University nor the names of its contributors 22 | * may be used to endorse or promote products derived from this software 23 | * without specific prior written permission. 24 | * 25 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 | * SUCH DAMAGE. 36 | * 37 | * @(#)utils.h 8.3 (Berkeley) 3/20/94 38 | */ 39 | 40 | /* utility definitions */ 41 | /* following hacked by acb, to be less dependant on POSIX */ 42 | #ifdef _POSIX2_RE_DUP_MAX 43 | #define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */ 44 | #else 45 | #define DUPMAX 255 46 | #endif 47 | #define INFINITY (DUPMAX + 1) 48 | #define NC (CHAR_MAX - CHAR_MIN + 1) 49 | typedef unsigned char uch; 50 | 51 | /* switch off assertions (if not already off) if no REDEBUG */ 52 | #ifndef REDEBUG 53 | #ifndef NDEBUG 54 | #define NDEBUG /* no assertions please */ 55 | #endif 56 | #endif 57 | #include 58 | 59 | /* for old systems with bcopy() but no memmove() */ 60 | #ifdef USEBCOPY 61 | #define memmove(d, s, c) bcopy(s, d, c) 62 | #endif 63 | -------------------------------------------------------------------------------- /scripts/brag.pb: -------------------------------------------------------------------------------- 1 | // convert the first character of a string to its uppercase equivalent 2 | 3 | %trans upcase-first: 4 | ".*": 0 u ; 5 | ; 6 | 7 | brag: frag end | 8 | frag brag | frag brag | frag brag | 9 | frag brag | frag brag | frag brag 10 | ; 11 | 12 | end: "Now give me some more of..." ; 13 | 14 | frag: 15 | "I " act "! " | 16 | "Pardon my language. " | 17 | "But " yell " let the " entities " bear witness! " | 18 | "Even in the belly of the Thunderbird I've been casting out the " entities "; I'm busting my " body-part " and blowing my O-ring, and ripe to throw a *loaf*! " | 19 | "For I speak *only* the " emphatic " *Truth*, and never in my days have I spoken other than! For my every utterance is a lie, including this very one you hear! " | 20 | "I say, `" slogan "'. By God, `" slogan "', I say! " | 21 | "I am " entity ", I am " entity "! " | 22 | "I'll drive a mile so as not to walk a foot; I am " entity "! " | 23 | "Yes, I'm " entity "! " | 24 | "I drank *" being "* under " number " tables, I am too " adjective " to die, I'm insured for acts o' God *and* Satan! " | 25 | "I was shanghaied by " entities " and " entities " from " place ", and got away with their hubcaps! " | 26 | "I *cannot* be tracked on radar! " | 27 | "I wear nothing uniform, I wear *no* " emphatic " uniform! " | 28 | "Yes baby, I'm " number " feet tall and have " number " rows o' " body-part "s; I was suckled by a " pet ", I gave " she-being " a high-protein tonsil wash! " | 29 | "I'm a bacteriological weapon, I am *armed* and *loaded*! " | 30 | "I'm a fission reactor, I fart plutonium, power plants are fueled by the " spoor " of my " body-part "; when they plug *me* in, the lights go out in " place "! " | 31 | "I weigh " number " pounds in zero gravity, *" attack "*! " | 32 | "I've sired " entities " across " place ", I cook and *eat* my dead; " yell " I'm the Unshaven Thorn Tree of " place "! " | 33 | "I " act "! " | 34 | being>upcase-first "'s hands are my *ideal* playground! " | 35 | "I hold the " number>upcase-first "-Bladed Windbreaker; the wheels that turn are behind me; I think *backwards*! " | 36 | "I do it for *fun*! " | 37 | "My imagination is a *" emphatic "* cancer and I'll pork it before it porks me! " | 38 | "They say a godzillion is the highest number there is. Well by God! I count to a godzillion and *one*! " | 39 | "Yes, I'm the purple flower of " place ", give me wide berth; when I drop my drawers, " being " swoons! " | 40 | "I use a " pet " for a prophylactic; I'm *thicker, harder* and *meaner* than the Alaskan Pipeline, and carry more " spoor "! " | 41 | "I'll freeze *your* " spoor " before it hits the bathroom tile! " | 42 | yell | 43 | "I kidnapped the future and ransomed it for the past, I made *" being "* wait up for me to bleed my " pet "! " | 44 | "My infernal " spoor " wilts the Tree of Life, I left my *" spoor "* on the Rock of Ages, *who'll " attack ", who'll spill their juice*? " | 45 | "Who'll " attack ", whose candle will I fart out? " | 46 | "Whoop! I'm ready! " | 47 | "So step aside, all you butt-lipped, neurotic, insecure bespectacled " entities "! " | 48 | "I'm " entity ", I am Not Insane! " | 49 | "I'm a screamer and a laugher, I " act ", I am a *sight*! " | 50 | "My physical type *cannot* be classified by science, my `familiar' is a " pet ", I feed it " entities "! " | 51 | "I communicate without *wires* or *strings*! " | 52 | "I am a Thuggee, I am feared in the Tongs, I have the Evil " body-part>upcase-first ", I carry the Mojo Bag; I swam *" place "* and didn't get wet! " | 53 | "I circumcize " entities " with my teeth and make 'em leave a tip; I change tires with my *tongue* and my *tool*! " | 54 | "Every night I hock up a lunger and extinguish the *Sun*! " | 55 | "I'm " entity ", who'll try to " attack "? " | 56 | "I've packed the brownies of the " entities ", I leak the Plague from my " body-part "s, opiates are the *mass* of my religion, *I " act "!* " | 57 | "Yes, I'm a rip-snorter, I cram coca leaves right into my " body-part "s before they're picked off the *tree*! " | 58 | "*" entities>upcase-first "* cringe at my tread! " | 59 | "I " act ". " | 60 | "I'm " adjective ", I'll live forever and remember it afterwards! " | 61 | "I'm " adjective "! " | 62 | "I'm " adjective "! " | 63 | "Come *on* and give me cancer, I'll spit up the tumor and butter my *bread* with the juice! " | 64 | "I'm " adjective ", I " act "! " | 65 | "My droppings bore through the earth and erupt *volcanoes* in *" place "*! " | 66 | "Yes, I can drink more wine and stay soberer than all the " entities " in " place "! " | 67 | yell "*" body-part>upcase-first " Blowout*! " | 68 | "I am a *Moray Eel*, I am a *Komodo Dragon*, I am the *Killer Whale bereft of its pup*! " | 69 | "I have a triple " body-part ", I was sired by " being ", give me *all* your Slack! " | 70 | "I told *" he-being "* I wouldn't go to church and He *shook my hand*! " | 71 | "I have my *own* personal saviors, I change 'em every hour, I don't give a fuck if there's life after death, I want to know if there's even any " emphatic " *Slack* after death! " | 72 | "I am a " emphatic " *visionary*, I see the future and the past in comic books and wine bottles; I eat *black holes* for breakfast! " | 73 | "I " act "! " | "I " act "! " | 74 | "I ran 'em out of Heaven and sold it to Hell for a *profit*! " | 75 | "I'm enlightened, I achieved `Nirvana' and took it *home* with me. " | 76 | yell | 77 | "I'm so ugly the Speed of Light can't slow me down and Gravity won't tug at my cuffs! " | 78 | slogan " " | slogan " " 79 | ; 80 | 81 | emphatic: "goddamn" | "god damn" |"GOD DAMN" | "fucking" 82 | ; 83 | 84 | attack: 85 | "blow me down" | "gouge with me" | "come and get me" | 86 | "tear flesh with me" 87 | ; 88 | 89 | spoor: "spoor" | "seed" | "breath" | "sweat" | "spew" 90 | ; 91 | 92 | number: "seven" | "23" | "13" | "666" | "273" | "42" 93 | ; 94 | 95 | entity: 96 | "a Crime Fighting Master Criminal" | "a "pet | 97 | "the bigfooted devil of Level 14" | 98 | "the last remaining Homo Correctus" | "the " emphatic " Man of the Future" | 99 | "a human being of the *first* " emphatic " water" | 100 | "the javalina humping junkie that jumped the " entities 101 | ; 102 | 103 | pet: "pterodactyl" | "python" | "triceratops" | "giant lizard" 104 | ; 105 | 106 | being: she-being | he-being 107 | ; 108 | 109 | she-being: "Mother Nature" | "God" | "the Anti-Virgin" 110 | ; 111 | 112 | he-being: "the Devil" | "Father Time" | "Jesus" | "the Wolf Man" 113 | ; 114 | 115 | entities: "bodiless fiends" | "alien jews" | "Men from Mars" | 116 | "heathen *Hindoos*" | "space monsters" | 117 | "sons of God and man" | "False Prophets" | "gods" | "dinosaurs" | 118 | "retarded space bastards" | "slabs o' wimp meat" | "dipshits" 119 | ; 120 | 121 | body-part: "nose" | "gut" | "arm-vein" | "nether part" | 122 | "backbone" | "brow" | "teat" 123 | ; 124 | 125 | yell: "YEEE HAW! " | "YEE! YEEE! " | "*Yip, yip, YEEEEEEE!* "| 126 | "YEEEEEHAW! " | "YAH-HOOOO! " 127 | ; 128 | 129 | slogan: "Fuck 'em if they can't take a joke!" | "Anything for a laugh!" | 130 | "When the Rapture comes, I'll make 'em wait!" | 131 | "They'll *never* clean *my* cage!" 132 | ; 133 | 134 | act: 135 | "pick the " emphatic " terror of the " emphatic " " entities " out of my *" body-part "*" | 136 | "pay no taxes" | "take drugs" | 137 | "make a *spectacle* of myself" | 138 | "wipe the *Pyramids* off my shoes before I enter *my* house" | 139 | "bend *crowbars* with my meat ax and a thought" | 140 | "bend my genes and whittle my DNA with the sheer force of my mighty *will*" | 141 | "steer my *own* " emphatic " evolution" 142 | ; 143 | 144 | adjective: 145 | "*fuel-injected*" | "*immune*" | "*radioactive*" | 146 | "*supernatural*" | "*intense*" 147 | ; 148 | 149 | place: 150 | "China" | "Hong Kong" | "Asia" | "the Atlantis Zoo" | "the Cosmos" | 151 | "a corporate galaxy" | "Hell County" | "the Bermuda Triangle" 152 | ; 153 | 154 | -------------------------------------------------------------------------------- /scripts/eqn.pb: -------------------------------------------------------------------------------- 1 | // eqn.pb acb Walpurgisnacht'95 2 | // generate interesting-looking but bogus LaTeX equations. 3 | 4 | eqn-start: eqn-prolog eqn-body eqn-epilog ; 5 | 6 | //eqn-prolog: ".br\n.br\n.br\n.EQ\nsize 36\ndelim %%\n.EN\n" ; 7 | //eqn-epilog: "\n.EN\n" ; 8 | //eqn-epilog: "\n" ; 9 | eqn-prolog: "\\documentstyle[a4wide,12pt]{report}\n\\begin{document}\n\\begin{Large}\n\\begin{center}\n\\vfill\n\\["; 10 | eqn-epilog: "\\]\n\\end{center}\n\\end{Large}\n\\end{document}"; 11 | 12 | eqn-body: lvalue " = " equation eqcont ; 13 | 14 | eqcont: "\\]\n\n\\[ = " equation eqcont | "" | "\\]\n\n\\[ = " equation eqcont | "\\]\n\n\\[ = " equation eqcont | "\\]\n\n\\[ = " equation eqcont 15 | | "" | "\\]\n\n\\[ = " equation eqcont ; 16 | 17 | lvalue: pronumeral | pronumeral " ( " pronumeral " ) " ; 18 | 19 | equation: "\\frac{" equation "}{" equation "}" 20 | | "\\frac{" equation "}{" equation "}" 21 | | pronumeral 22 | | pronumeral "_{" pronumeral "}" 23 | | pronumeral "_{" polynomial(pronumeral) "}" 24 | | sum(pronumeral) 25 | | integral(pronumeral) 26 | | polynomial(pronumeral) 27 | | "\\sqrt{" equation " }" 28 | | equation "+" equation 29 | | equation "-" equation 30 | ; 31 | 32 | sum(pn): "\\sum_{" pn "=" from "}^{" to "} " pronumeral "_" pn ; 33 | 34 | integral(pn): "\\int_{" pn "=" from "}^{" to "} " pronumeral "_" pn ".d" pn ; 35 | 36 | from: pronumeral | "-{\\infty}" | "0" ; 37 | 38 | to: pronumeral | "\\infty" ; 39 | 40 | polynomial(pn): linear(pn) | quadratic(pn) | cubic(pn) ; 41 | 42 | linear(pn): int " " pn " " plusminus " " int ; 43 | 44 | quadratic(pn): int " " pn "^{2}" plusminus linear(pn) ; 45 | 46 | cubic(pn): int " " pn "^{3}" plusminus quadratic(pn) ; 47 | 48 | pronumeral: "x" | "y" | "t" | "{\\alpha}" | "{\\beta}" | "{\\gamma}" 49 | | "{\\delta}" | "{\\epsilon}" | "{\\zeta}" | "{\\eta}" | "{\\theta}" 50 | | "{\\iota}" | "{\\kappa}" | "{\\mu}" | "{\\nu}" | "{\\xi}" 51 | | "{\\pi}" | "{\\rho}" | "{\\sigma}" | "{\\tau}" | "{\\upsilon}" 52 | | "{\\phi}" | "{\\chi}" | "{\\psi}" | "{\\omega}" ; 53 | 54 | int: digit int | digit ; 55 | 56 | digit: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; 57 | 58 | plusminus: "+" | "-" ; 59 | 60 | 61 | -------------------------------------------------------------------------------- /scripts/exam.pb: -------------------------------------------------------------------------------- 1 | // exam,pb acb sometime 3161 2 | // generate intimidating but bogus exam questions 3 | 4 | question: question-2 | question-2 5 | | question-2 "Be sure to refer to " issue " in your answer. " 6 | | question-2 "Include " evidence-type ". " 7 | ; 8 | 9 | question-2: "Compute the " something-of " of " something ". " 10 | | "Are " plural " " classification "? Discuss. " 11 | | "Is " singular " " classification "? Discuss. " 12 | | "Express " something " in " express-in-what ". " 13 | | "Show that the " something-of " of " something " is " result ". " 14 | ; 15 | 16 | issue: theorem-source "'s Theorem" | theory-type " theory" 17 | | "Plutonium Atom Totality" | "the " ordinal " law of " law-of-this 18 | ; 19 | 20 | theorem-source: "Godel" | "Wibbel" | "Abian" | "Turing" | "Euler" 21 | | "Fermat" | "Bell" 22 | ; 23 | 24 | theory-type: "game" | "set" | "match" | "interstice" | "information" 25 | | "ring" | "group" | "graph" 26 | ; 27 | 28 | law-of-this: "thermodynamics" | "conservation of matter" | "gravity" 29 | ; 30 | 31 | express-in-what: "canonical form" | "normal form" | "the " tag " domain" ; 32 | 33 | something-of: something-of-2 | adjective " " something-of-2 34 | | tag "-" something-of-2 ; 35 | 36 | adjective: "canonical" | "minimal" | "maximal" | "inverse" ; 37 | 38 | something-of-2: "closure" | "determinant" | "matrix" | "path" | "correlation" ; 39 | 40 | plural: adjective " " plural-2 ; 41 | 42 | pluralise: ".*" -> "$"/"s" ; 43 | 44 | plural-2: "trees" | "matrices" ; 45 | 46 | singular: adjective " " singular-2 ; 47 | 48 | singular-2: "search" | "factorisation" ; 49 | 50 | result: number | "{ }" | "infinity" | "uncomputable" | "the null set" ; 51 | 52 | evidence-type: "flowcharts" | "Feynman diagrams" | "Venn diagrams" 53 | ; 54 | 55 | something: number | set-of-numbers ; 56 | 57 | set-of-numbers: "{ " numbers " } " ; 58 | 59 | numbers: number " " numbers | number ; 60 | 61 | number: digit number | digit ; 62 | 63 | digit: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; 64 | 65 | classification: tag "-complete" 66 | ; 67 | 68 | // a tag, used to make concepts seem more intimidating 69 | 70 | tag: greek-letter | roman-letter | roman-letter roman-letter; 71 | 72 | roman-letter: "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" 73 | | "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" 74 | | "V" | "W" | "X" | "Y" | "Z" ; 75 | 76 | greek-letter: "alpha" | "beta" | "gamma" | "delta" | "epsilon" | "lambda" | 77 | "sigma" | "theta" | "phi" | "rho" | "omega" ; 78 | 79 | ordinal: "first" | "second" | "third" | "fourth" | "fifth" ; 80 | 81 | -------------------------------------------------------------------------------- /scripts/legal.pb: -------------------------------------------------------------------------------- 1 | // legal.pb 2 | // legalese generator 3 | // v1.1 mitch 19-2-96 4 | 5 | legal: statement>upcase-first 6 | ; 7 | 8 | statement: 9 | [qualification ", " | ""] [condition | "" ] pronouncement [", " qualification | ""] "." 10 | ; 11 | 12 | // convert the first character of a string to its uppercase equivalent 13 | 14 | %trans upcase-first: 15 | ".*": 0 u ; 16 | ; 17 | 18 | thin: 19 | [thing | things] 20 | ; 21 | 22 | things: 23 | "eligible telecommunications carriers" | 24 | "exempt telecommunications companies" | 25 | "broadcast services" | 26 | "special provisions concerning " thin | 27 | "broadcast license renewal procedures" | 28 | "automated ship distress and safety systems" | 29 | "restrictions on " thin | 30 | "over-the-air reception devices" | 31 | "cable services" | 32 | "navigation devices" | 33 | "telecommunications services" | 34 | "video programming services provided by telephone companies" | 35 | "unnecessary Commission regulations and functions" 36 | ; 37 | 38 | thing: 39 | "broadcast spectrum flexibility" | 40 | "broadcast ownership" | 41 | "term of licenses" | 42 | "direct broadcast satellite service" | 43 | "Cable Act reform" | 44 | "cable service provided by telephone companies" | 45 | "preemption of " thin | 46 | "franchising authority regulation of " thin | 47 | "local exchange carrier" | 48 | "telecommunications services" | 49 | "competitive availability of " thin | 50 | "video programming accessibility" | 51 | "regulatory forbearance" | 52 | "elimination of " thin | 53 | "unnecessary Commission regulations and functions" 54 | ; 55 | 56 | condition: 57 | "whenever in this Act " section " is expressed in terms of " section ", " 58 | ; 59 | 60 | section: 61 | "an amendment or repeal" | 62 | "an amendment to, or repeal of, a section or other provision" | 63 | "a section or other provision of the Communications Act of 1934 (47 U.S.C. 151 et seq.)" | 64 | "section 3 of the Communications Act of 1934 (47 U.S.C. 153)" 65 | ; 66 | 67 | pronouncement: 68 | "the reference shall be considered to be made to " section | 69 | "the terms used in this Act have the meanings provided in section 3 of the Communications Act of 1934 (47 U.S.C. 153)" | 70 | term | amend | gen-duty 71 | ; 72 | 73 | qualification: 74 | "except as otherwise expressly provided" | 75 | "except as otherwise provided in this Act" | 76 | "as amended by this section" 77 | ; 78 | 79 | term: 80 | "the term `" thin "' " meaning 81 | ; 82 | 83 | meaning: 84 | "has the meaning given such term in section 602" | 85 | "means " definition 86 | ; 87 | 88 | definition: 89 | "equipment employed on the premises of a person (other than a carrier) to originate, route, or terminate telecommunications" | 90 | "that a person that is not an affiliate of a " thing " is able to provide " things " in such a manner that customers have " power | 91 | " a local exchange carrier operating entity to the extent that such entity:" act "; " act "; or " act "." | 92 | " any provider of telecommunications services, except that such term does not include aggregators of telecommunications services (as defined in section 226)." 93 | ; 94 | 95 | power: 96 | "the ability to route automatically, without the use of any " thing ", their " things " to the " thing " of the customer's designation from among 2 or more " things " (including such " thing ")" 97 | ; 98 | 99 | also: 100 | "Such term also includes features, 101 | functions, and capabilities that are provided by means of such 102 | facility or equipment, including subscriber numbers, databases, 103 | signaling systems, and information sufficient for billing and 104 | collection or used in the transmission, routing, or other 105 | provision of a telecommunications service." 106 | ; 107 | 108 | amend: 109 | "Section 3 (47 U.S.C. 153) is amended:" amending 110 | ; 111 | 112 | amending: 113 | " " amend2 | 114 | " " amends "; and " amend2 115 | ; 116 | 117 | amends: 118 | " " amend2 "; " amends | 119 | " " amend2 "; " amends | 120 | " " amend2 "; " amends | 121 | " " amend2 "; " amends | 122 | " " amend2 "; " amends | 123 | " " amend2 124 | ; 125 | 126 | amend2: 127 | "in subsections (e) and (n), by redesignating clauses (1), (2), and (3), as clauses (A), (B), and (C), respectively" | 128 | "in subsection (w), by redesignating paragraphs (1) through (5) as subparagraphs (A) through (E), respectively" | 129 | "in subsections (y) and (z), by redesignating paragraphs (1) and (2) as subparagraphs (A) and (B), respectively" | 130 | "by redesignating subsections (a) through (ff) as paragraphs (1) through (32)" | 131 | "by indenting paragraphs (1) through (32) 2 em spaces" | 132 | "by changing the first letter of each defined term in such paragraphs from a capital to a lower case letter (except for `United States', `State', `State commission', and `Great Lakes Agreement')" | 133 | "by reordering such paragraphs and the additional paragraphs added by subsection (a) in alphabetical order based on the headings of such paragraphs and renumbering such paragraphs as so reordered" | 134 | "in section 225(a)(1), by striking `section 3(h)' and inserting `section 3'" | 135 | "in section 332(d), by striking `section 3(n)' each place it appears and inserting `section 3'" | 136 | "in sections 621(d)(3), 636(d), and 637(a)(2), by striking `section 3(v)' and inserting `section 3'" 137 | ; 138 | 139 | place: 140 | "any incorporated place of 10,000 inhabitants or more, or any part thereof, based on the most recently available population statistics of the Bureau of the Census" | 141 | "any territory, incorporated or unincorporated, included in an urbanized area, as defined by the Bureau of the Census as of August 10, 1993" 142 | ; 143 | 144 | fashion: 145 | " for the transmission and routing of telephone exchange service and exchange access" | 146 | " at any technically feasible point within the carrier's network" | 147 | " that is at least equal in quality to that provided by the local exchange carrier to itself or to any subsidiary, affiliate, or any other party to which the carrier provides interconnection" | 148 | " on rates, terms, and conditions that are just, reasonable, and nondiscriminatory, in accordance with the terms and conditions of the agreement and the requirements of this section and section 252" 149 | ; 150 | 151 | act: 152 | " provides common carrier service to any local exchange carrier study area that does not include either: " place "; or " place | 153 | " provides telephone exchange service, including exchange access, to fewer than 50,000 access lines" | 154 | " provides telephone exchange service to any local exchange carrier study area with fewer than 100,000 access lines" | 155 | " has less than 15 percent of its access lines in communities of more than 50,000 on the date of enactment of the Telecommunications Act of 1996" 156 | ; 157 | 158 | amend4: " A telecommunications carrier shall be treated 159 | as a common carrier under this Act only to the extent that it 160 | is engaged in providing telecommunications services, except 161 | that the Commission shall determine whether the provision of 162 | fixed and mobile satellite service shall be treated as common 163 | carriage." 164 | ; 165 | 166 | gen-duty: 167 | "each telecommunications carrier has the duty: " duties 168 | ; 169 | 170 | duties: 171 | [ ["not" | ""] duty | ["not" | "" ] duty fashion] | 172 | dutylist "; and " [ ["not" | ""] duty | ["not" | "" ] duty fashion] 173 | ; 174 | 175 | dutylist: 176 | dutylist "; " [ ["not" | ""] duty | ["not" | "" ] duty fashion] | 177 | dutylist "; " [ ["not" | ""] duty | ["not" | "" ] duty fashion] | 178 | dutylist "; " [ ["not" | ""] duty | ["not" | "" ] duty fashion] | 179 | dutylist "; " [ ["not" | ""] duty | ["not" | "" ] duty fashion] | 180 | dutylist "; " [ ["not" | ""] duty | ["not" | "" ] duty fashion] | 181 | [ ["not" | ""] duty | ["not" | "" ] duty fashion] 182 | ; 183 | 184 | duty: 185 | " to interconnect directly or indirectly with the facilities and equipment of other telecommunications carriers" | 186 | " to install network features, functions, or capabilities that do not comply with the guidelines and standards established pursuant to section 255 or 256" | 187 | " to prohibit, and not to impose unreasonable or discriminatory conditions or limitations on, the resale of its telecommunications services" | 188 | " to provide, to the extent technically feasible, number portability in accordance with requirements prescribed by the Commission" | 189 | " to provide dialing parity to competing providers of telephone exchange service and telephone toll service" | 190 | " to permit all providers to have nondiscriminatory access to telephone numbers, operator services, directory assistance, and directory listing, with no unreasonable dialing delays" | 191 | " to negotiate in good faith in accordance with section 252 the particular terms and conditions of agreements to fulfill the duties described in paragraphs (1) through (5) of subsection (b) and this subsection" | 192 | " to provide, for the facilities and equipment of any requesting telecommunications carrier, interconnection with the local exchange carrier's network" 193 | ; 194 | 195 | 196 | -------------------------------------------------------------------------------- /scripts/loop.pb: -------------------------------------------------------------------------------- 1 | loop: l o o p co sp op 2 | po sc 3 | o p co sp qu op qu sc 4 | s o co sp 5 | l o sp s c sp l sp o sp c o sp s p sp q u sp 6 | so po qu sc 7 | c co sp qu c qu sc l co sp qu l qu sc o co sp qu o qu sc 8 | p co sp qu p qu sc q co sp qu q qu sc s co sp qu s qu sc u co sp qu u qu sc 9 | s c co sp qu sc qu sc 10 | c o co sp qu co qu sc s p co sp qu sp qu sc 11 | q u co sp qu sl qu qu sc s l co sp qu sl sl qu sc 12 | ; 13 | 14 | op: "l o o p co sp op 15 | po sc 16 | o p co sp qu op qu sc 17 | s o co sp 18 | l o sp s c sp l sp o sp c o sp s p sp q u sp 19 | so po qu sc 20 | " 21 | ; 22 | 23 | so: lo sc l o co sp qu lo qu sc 24 | p o co sp qu 25 | ; 26 | 27 | lo: "lo qu sc 28 | p o co sp qu" 29 | ; 30 | 31 | po: "c co sp qu c qu sc l co sp qu l qu sc o co sp qu o qu sc 32 | p co sp qu p qu sc q co sp qu q qu sc s co sp qu s qu sc u co sp qu u qu sc 33 | s c co sp qu sc qu sc 34 | c o co sp qu co qu sc s p co sp qu sp qu sc 35 | q u co sp qu sl qu qu sc s l co sp qu sl sl qu sc" 36 | ; 37 | 38 | c: "c" 39 | ; 40 | 41 | l: "l" 42 | ; 43 | 44 | o: "o" 45 | ; 46 | 47 | p: "p" 48 | ; 49 | 50 | q: "q" 51 | ; 52 | 53 | s: "s" 54 | ; 55 | 56 | u: "u" 57 | ; 58 | 59 | sc: " 60 | ; 61 | 62 | " 63 | ; 64 | 65 | co: ":" 66 | ; 67 | 68 | sp: " " 69 | ; 70 | 71 | qu: "\"" 72 | ; 73 | 74 | sl: "\\" 75 | ; 76 | 77 | 78 | -------------------------------------------------------------------------------- /scripts/manifesto.pb: -------------------------------------------------------------------------------- 1 | // a grammar for making manifestoes; parts culled from the postmodernism 2 | // grammar and other places. 3 | // acb sometime in 1995 4 | 5 | 6 | S: prologue body epilogue ; 7 | 8 | prologue: { pointnum=1 } ; 9 | 10 | body: title points ; 11 | 12 | epilogue: "" ; 13 | 14 | title: "The " movement " Manifesto:\n" ; 15 | 16 | movement: movement-prefix movement-2 | movement-prefix movement 17 | | movement-prefix movement-2 | movement-prefix movement 18 | ; 19 | 20 | movement-prefix: "Neo" | "Sur" | "Para" | "Pata" | "Meta" | "Post" | "Anti" 21 | | "Non" | "Cyber" 22 | ; 23 | 24 | movement-2: "Nihilist" | "Existentialist" | "Realist" | "Objectivist" 25 | | "Ismist" | "Positivist" | "Negativist" 26 | ; 27 | 28 | points: points points point 29 | | points point point 30 | | point point 31 | ; 32 | 33 | point: $pointnum ". " statement "\n" 34 | { 35 | pointnum=pointnum+1 36 | } ; 37 | 38 | statement: big-thing " is dead." 39 | | big-thing " is dead; " is-dead-explanation 40 | | big-thing " is a myth." 41 | | big-thing " is an illusion." 42 | | attribute-paradox-1(attribute) 43 | | thing-paradox-1(abstract-noun) 44 | | "there is no " nonbeable ". " 45 | | "those who " do-silly-thing " are " plural-derog-noun ". " 46 | | "we are all " what-we-are "." 47 | | big-thing " is nothing more than " mere-thing "." 48 | ; 49 | 50 | mere-thing: "noise" | "the background noise of " big-thing 51 | | "a stupid game" | "an obscene jest" | "a bad joke" 52 | ; 53 | 54 | what-we-are: what-we-are-2 | what-we-are-2 " who think they're " human-adj 55 | | "liars" 56 | | "victims of " big-thing | "doomed to endless " endless-thing-2 57 | ; 58 | 59 | // uniquely human, positive traits 60 | human-adj: "conscious" | "free" | "intelligent" | "self-aware" ; 61 | 62 | what-we-are-2: "automata" | "sheep" | "puppets" ; 63 | 64 | do-silly-thing: "believe that " silly-belief 65 | | "seek " ideal-positive-attribute 66 | | "seek " ideal-positive-attribute " in " big-thing 67 | ; 68 | 69 | silly-belief: "there is " nonbeable>prepend-a-or-an 70 | | big-thing " will save " big-thing 71 | | big-thing " is " higher-state-of-being 72 | ; 73 | 74 | higher-state-of-being: "transcendent" | "liberating" | "independent" 75 | | "free" | "unlimited" | "beneficial" 76 | ; 77 | 78 | plural-derog-noun: "fools" | "idiots" 79 | ; 80 | 81 | prepend-a-or-an: 82 | "a*" -> "^"/"an " 83 | "e*" -> "^"/"an " 84 | "i*" -> "^"/"an " 85 | "o*" -> "^"/"an " 86 | "u*" -> "^"/"an " 87 | "*" -> "^"/"a " 88 | ; 89 | 90 | nonbeable: "escape" | "God" | "Santa Claus" | "free lunch" | "salvation" 91 | | "hope" | "recovery" | "Maxwell's Demon" | "end to the " endless-thing 92 | ; 93 | 94 | endless-thing: endless-thing-2 | "continuum of " endless-thing-2 ; 95 | 96 | endless-thing-2: "monotony" | "recursion" | "redundancy" 97 | ; 98 | 99 | // paradoxes, paradoys and paradozzes 100 | 101 | thing-paradox-1(thing): thing " is the " maximum-adj " " opposite(thing) ". " 102 | ; 103 | 104 | maximum-adj: "greatest" | "first" | "biggest" | "original" 105 | ; 106 | 107 | abstract-noun: "truth" ; 108 | 109 | attribute-paradox-1(attribute): 110 | "the most " attribute " thing is the " completely-synonym 111 | " " opposite(attribute) 112 | "." 113 | | "there is nothing more " attribute " than that which is " 114 | opposite(attribute) "." 115 | ; 116 | 117 | completely-synonym: "completely" | "totally" | "absolutely" ; 118 | 119 | attribute: "true" | "meaningful" | "false" ; 120 | 121 | opposite(word): @word>opposite-map>append-synonyms ; 122 | 123 | opposite-map: 124 | "true" <-> "false" 125 | "meaningful" <-> "absurd" 126 | "truth" <-> "lie" 127 | ; 128 | 129 | append-synonyms: 130 | ".*" -> "$"/"-synonyms" 131 | ; 132 | 133 | true-synonyms: "true"; 134 | false-synonyms: "false"; 135 | meaningful-synonyms: "meaningful"; 136 | absurd-synonyms: "absurd" | "meaningless"; 137 | lie-synonyms: "lie" ; 138 | 139 | // words above are dereferenceable 140 | 141 | 142 | // rules for "* is dead"-type sentences 143 | 144 | is-dead-explanation: big-thing " killed it. " 145 | | "it committed suicide. " 146 | | "the cause of death is " cause-of-death ". " 147 | | "it died of " cause-of-death 148 | ; 149 | 150 | cause-of-death: "gluttony" | "boredom" | "infinite recursion" 151 | | "despair at its own " introspective-attribute 152 | | "infinite regress" 153 | | introspective-attribute 154 | ; 155 | 156 | introspective-attribute: "futility" | "absurdity" | "meaninglessness" 157 | | "lack of " ideal-positive-attribute 158 | ; 159 | 160 | ideal-positive-attribute: "coherency" | "consistency" | "meaning" | "truth" 161 | ; 162 | 163 | 164 | // stuff culled from pomo 165 | // and hacked over a bit 166 | 167 | big-thing: "society" | "class" | "civilisation" 168 | | "culture" | "language" | "art" | "reality" | "truth" 169 | | "sexuality" | "consciousness" | "humanity" | "personhood" 170 | | "individuality" | "history" | "technology" ; 171 | -------------------------------------------------------------------------------- /scripts/silly-word.pb: -------------------------------------------------------------------------------- 1 | // silly.pb a script for generating silly words 2 | // Copyright (C) 1995, Andrew C. Bulhak 3 | 4 | word: word2 | prefix word2 ; 5 | 6 | word2: random-syllable suffix 7 | | random-syllable 8 | | random-syllable "o" random-syllable suffix 9 | | double(random-syllable) 10 | | random-syllable wordlet 11 | ; 12 | 13 | double(foo): foo foo ; 14 | 15 | prefix-or-random: prefix | random-syllable ; 16 | 17 | random-syllable: random-syllable-2 | plosive-cons-a random-syllable-2 ; 18 | 19 | random-syllable-2: consonant vowel sibilant-cons // `fut' 20 | | sibilant-bit vowel plosive-cons 21 | | consonant vowel double(plosive-cons-a) 22 | | double-around(consonant vowel) 23 | | double-around(consonant "oo") 24 | | sibilant-bit vowel sibilant-cons plosive-cons-b // ``schlorpht'' 25 | | interleave-two-with-one(consonant consonant vowel) // "bodo" 26 | ; 27 | 28 | // some ready-made silly wordlets, some with a distinctly hackerly flavour 29 | 30 | wordlet: "snarf" | "gronk" | "blat" | "gweep" ; 31 | 32 | double-around(foo bar): foo bar foo ; 33 | 34 | interleave-two-with-one(foo bar baz): foo baz bar baz ; 35 | 36 | prefix: "ur" | "meta" | "neo" | "pro" | "" ; 37 | 38 | suffix: "le" | "licious" | "plex" | "tude" | "lap" | "ity" | "ie" ; 39 | 40 | vowel: "a" | "e" | "i" | "o" | "u" | "ea" | "ee" | "oo" 41 | "ar" | "or" ; 42 | 43 | consonant: "b" | "c" | "d" | "f" | "g" | "h" | "j" | "k" | "l" | "m" | "n" | "p" | "q" | "r" | "s" | "t" | "v" | "w" | "x" | "y" | "z" | "w" | "w" | "w" | "qu"; 44 | 45 | sibilant-bit: sibilant-cons | sibilant-cons post-sibilant ; 46 | 47 | // a letter or string which may specifically be appended to a sibilant consonant 48 | post-sibilant: "l" | "n" ; 49 | 50 | sibilant-cons: "f" | "ph" | "s" | "sh" | "sch" | "x" | "z"; 51 | 52 | plosive-cons: plosive-cons-a | plosive-cons-b ; 53 | 54 | plosive-cons-a: "b" | "d" | "p" ; 55 | plosive-cons-b: "t" | "k" | "ck" ; 56 | 57 | -------------------------------------------------------------------------------- /scripts/spout.pb: -------------------------------------------------------------------------------- 1 | // spout.pb SUBGENIUS PROFUNDITIES GENERATION MATRIX 2 | // "Imparted to Dr. Armand Gideon, 1st Church of "Bob," Scientist and 3 | // further wrangled by Rev. Ivan Stang, 1st MegaFisTemple Lodge." 4 | // found at SubSite, converted to dada-engine format by mitch, 25-1-96 5 | 6 | spout: one " " two " " three " " four ; 7 | 8 | one: 9 | "The awesome power" | "The unspeakable PeE-Gospel" | 10 | "The mind-blasting prophecy" | "The cosmic joke" | 11 | "Any Xist intervention with the Conspiracy" | "The demonic UFO fleet" | 12 | "Any fragments of the Truth" | 13 | "The concept of \"Slack\"" | 14 | "The absolute stupidity" | 15 | "The entity called \"Bob\"" 16 | ; 17 | 18 | two: 19 | "of Jehovah-1" | "wielded by Nhee Ghee" | 20 | "claimed by \"Pink Boys\"" | "masquerading as a manifestation of sexhurt" | 21 | "possessed by The Fightin' Jesus" | "used to control the earth" | 22 | "of a million False Prophets" | "known to Emergentiles and Rewardians alike" | 23 | "in the bowels of the Aesir" | "seen once a Millenium" 24 | ; 25 | 26 | three: 27 | "can perhaps be" | "must without question be" | 28 | "can be \"sold\" to humanity if it is" | 29 | "evolves until it is manipulated by the Con and can alter your soul so that you are yet" | 30 | "cannot possibly ever be" | 31 | "fucks that which can be, figuratively, 'smoked in \"Bob's\" Pipe' until it is" | 32 | "is cursed to be eternally" | "was implanted in our minds only to be" | 33 | "could have triumphed had it not been" | 34 | "is 'of \"Bob\"' only if it is" 35 | ; 36 | 37 | four: 38 | "grossly underestimated and over-priced." | 39 | "part of the Conspiracy." | 40 | "of utmost concern to the fate of the planet." | 41 | "put out of its misery." | 42 | "examined and exorcised from this so-called 'reality.'" | 43 | "driven into the ground." | 44 | "recreated purely by 'chance,' thenceforth probably to be eaten by rats in Hell." | 45 | "discounted as hallucination." | 46 | "diagnosed by \"DoktorS.\"" | 47 | "loved, yet judged and found wanting, by \"Bob.\"" 48 | ; 49 | 50 | -------------------------------------------------------------------------------- /scripts/test/bogus.pb: -------------------------------------------------------------------------------- 1 | // this should produce a (non-syntactic) error when read, because of 2 | // the symbol "undefined". 3 | 4 | foo: bar baz 5 | ; 6 | 7 | bar : undefined | "xyzzy" ; 8 | 9 | baz : "plugh" ; 10 | -------------------------------------------------------------------------------- /scripts/test/cascading.pb: -------------------------------------------------------------------------------- 1 | // test cascading parameters for brokenness 2 | start: foo("blah"); 3 | foo(baz): bar(baz) bar(baz) ; 4 | bar(baz): "[" baz "]" ; 5 | -------------------------------------------------------------------------------- /scripts/test/codetest.pb: -------------------------------------------------------------------------------- 1 | s: { i=0 } s0 ; 2 | 3 | s0: s0 foo | foo | s0 foo ; 4 | 5 | foo: { i=i+1 } $i "\n" ; 6 | -------------------------------------------------------------------------------- /scripts/test/concattest.pb: -------------------------------------------------------------------------------- 1 | s: { res="\n" ; c=0 } a $res ; 2 | 3 | a: a b | a c | b | c ; 4 | 5 | b: $c { res=res+"foo" ; c=c+1 }; 6 | 7 | c: $c { res=res+"bar" ; c=c+1 }; 8 | -------------------------------------------------------------------------------- /scripts/test/digits.pb: -------------------------------------------------------------------------------- 1 | // digits.pb acb 7-6-1995 2 | // print out a series of randomly-selected digits. Used to determine 3 | // bogosities in probability distributions. 4 | 5 | S: A + ; 6 | 7 | A: digit digit digit digit digit ; 8 | 9 | digit: "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; -------------------------------------------------------------------------------- /scripts/test/inlinechoice.pb: -------------------------------------------------------------------------------- 1 | S: T T T T T ; 2 | T: "("[ "foo" | "bar" ]")"; 3 | -------------------------------------------------------------------------------- /scripts/test/maptest.pb: -------------------------------------------------------------------------------- 1 | // a simple script to test regex-based mappings 2 | 3 | // a mapping definition: this one is a simple rule for converting plural nouns 4 | // to singular ones 5 | 6 | depluralise: 7 | ".*s" -> "s$" / "" 8 | ; 9 | 10 | // another one: this time, it converts (some) verbs to past tense. 11 | 12 | pasttense: 13 | ".*" -> "$" / "ed" 14 | ; 15 | 16 | // productions follow 17 | 18 | sentence: np " " vp ; 19 | 20 | np: //"the " noun 21 | // | 22 | "a " noun>depluralise # trim off any trailing 's's 23 | ; 24 | 25 | vp: "shall " verb 26 | | verb>pasttense 27 | ; 28 | 29 | noun: "bees" | "boy" | "ball" | "balloons" ; 30 | 31 | verb: "touch" | "kick" | "mention" ; 32 | -------------------------------------------------------------------------------- /scripts/test/paramtest.pb: -------------------------------------------------------------------------------- 1 | sentence: double(fruit) ; 2 | 3 | double(foo): foo " and " foo ; 4 | 5 | fruit: "apples" | "oranges" | "lemons" ; 6 | -------------------------------------------------------------------------------- /scripts/test/plus_star.pb: -------------------------------------------------------------------------------- 1 | /* test the * and + operators */ 2 | 3 | S: S1 "\n" S2 "\n" ; 4 | 5 | S1: A1* ; 6 | 7 | S2: A2+ ; 8 | 9 | A1: "This should appear 0 or more times.\n"; 10 | 11 | A2: "This should appear 1 or more times.\n"; -------------------------------------------------------------------------------- /scripts/test/repeattest.pb: -------------------------------------------------------------------------------- 1 | S: s1 s2 ; 2 | 3 | s1: %repeat("blah",3); 4 | 5 | s2: { foo=10/2 } %repeat("foo",foo); -------------------------------------------------------------------------------- /scripts/test/resource_decl.pb: -------------------------------------------------------------------------------- 1 | // test the resource keyword 2 | 3 | %resource foo: "hastur" ; 4 | 5 | bar: "blah"; 6 | 7 | -------------------------------------------------------------------------------- /scripts/test/test.pb: -------------------------------------------------------------------------------- 1 | // test.pb acb 10-9-1994 2 | // test script for psychobabble. 3 | // With apologies to Lewis Carroll. 4 | 5 | // the start symbol 6 | 7 | sentence : np " " vp "." ; 8 | 9 | // noun phrase 10 | 11 | np : prep " " noun 12 | | prep " " adj " " noun 13 | ; 14 | 15 | prep : "a" | "the"; 16 | 17 | adj : "brillig" | "slithy" | "mimsy" | "frumious" | "vorpal" | "manxome" 18 | | "uffish" | "tulgey" | "frabjous" ; 19 | 20 | // singular nouns 21 | noun : "frob" | "goret" | "beable" | "widget" | "futplex" ; 22 | 23 | vp : pverb " " np 24 | | "shall " fverb " " np 25 | | fverb " " np 26 | ; 27 | 28 | pverb : "frobnicated" | "frobbed" | "wugged" ; 29 | 30 | fverb : "frobnicate" | "frob" | "wug"; #the last verb dedicated to Chickenman 31 | 32 | -------------------------------------------------------------------------------- /scripts/test/test2.pb: -------------------------------------------------------------------------------- 1 | output: output sentence 2 | | sentence 3 | ; 4 | 5 | sentence: np " " vp ". " 6 | ; 7 | 8 | prep: "the" | "a" | "some" ; 9 | 10 | np: prep " " adj " " noun 11 | | prep " " noun 12 | | prep " " noun " with " np 13 | ; 14 | 15 | adj: "large" | "small" | "green" | "octangular" | "elongated" 16 | ; 17 | 18 | noun: "table" | "duck" | "boy" | "tree" | "ball" | "mushroom" | 19 | "watermelon" | "dragon" | "circle" | "planet"; 20 | 21 | vp: pverb " " np 22 | ; 23 | 24 | pverb: "took" | "touched" | "pushed" | "moved" | "dropped" | "frobbed" 25 | | "rotated" | "removed" | "positioned" 26 | ; 27 | 28 | -------------------------------------------------------------------------------- /scripts/test/xformtest.pb: -------------------------------------------------------------------------------- 1 | %trans foo: 2 | "bar" : s "baz" "quux" ; 3 | "frod" : d; 4 | ; 5 | 6 | %trans bar: 7 | "beable" : s "futplex" "urlap" ; 8 | ; 9 | -------------------------------------------------------------------------------- /src/Makefile.in: -------------------------------------------------------------------------------- 1 | # directories where things are installed go below 2 | 3 | CC = @CC@ 4 | YACC = @YACC@ 5 | LEX = @LEX@ 6 | RANLIB = @RANLIB@ 7 | 8 | # the pb language library 9 | LIBPB_OBJS = check.o dict.o dstring.o dump.o machine.o map.o ptrlist.o \ 10 | resolve.o resstack.o rtn.o strfunc.o transform.o variables.o 11 | 12 | PB_OBJS = pb.o y.tab.o lex.yy.o wrap.o 13 | #PBC_OBJS = pbc.o y.tab.o lex.yy.o rtn.o strfunc.o dstring.o check.o map.o \ 14 | # ptrlist.o variables.o transform.o machine.o ${REGEX} ${EXTRAOBJS} \ 15 | # emit_ps.o resolve.o dump.o 16 | #CFLAGS = -g ${INCDIRS} ${DEFINES} 17 | CFLAGS = -g @REGEXP_INCLUDE@ ${DEFINES} 18 | 19 | all: pb 20 | 21 | libpb.a: $(LIBPB_OBJS) 22 | ar ruv libpb.a $(LIBPB_OBJS) 23 | $(RANLIB) libpb.a 24 | 25 | pb: $(PB_OBJS) libpb.a 26 | $(CC) -o pb ${PB_OBJS} -L. -lpb @LIBS@ @REGEXP_LIB@ 27 | 28 | #pbc: $(PBC_OBJS) 29 | # $(CC) -o pbc $(PBC_OBJS) 30 | 31 | pb.o: pb.c rtn.h check.h map.h transform.h 32 | 33 | emit_ps.o: emit_ps.c rtn.h map.h transform.h 34 | 35 | y.tab.o: y.tab.c rtn.h resolve.h check.h map.h ptrlist.h transform.h machine.h 36 | 37 | lex.yy.o: lex.yy.c rtn.h strfunc.h y.tab.h map.h transform.h machine.h 38 | 39 | rtn.o: rtn.c rtn.h ptrlist.h 40 | 41 | strfunc.o: strfunc.c strfunc.h 42 | 43 | dstring.o: dstring.c dstring.h 44 | 45 | y.tab.c: parser.y 46 | ${YACC} -d -v parser.y 47 | 48 | lex.yy.c: lexer.x 49 | ${LEX} lexer.x 50 | 51 | dump.o: dump.c rtn.h map.h transform.h 52 | 53 | resolve.o: resolve.c resolve.h rtn.h dstring.h map.h ptrlist.h transform.h machine.h variables.h 54 | 55 | check.o: check.c check.h rtn.h map.h ptrlist.h 56 | 57 | map.o: map.c map.h 58 | 59 | ptrlist.o: ptrlist.c ptrlist.h 60 | 61 | variables.o: variables.c 62 | 63 | transform.o: transform.c transform.h 64 | 65 | machine.o: machine.c machine.h variables.h strfunc.h rtn.h resolve.h 66 | 67 | resstack.o: resstack.c resstack.h dict.h 68 | 69 | dict.o: dict.c dict.h 70 | 71 | wrap.o: wrap.c 72 | 73 | 74 | lextest: lextest.o lex.yy.o strfunc.o 75 | 76 | lextest.o: lextest.c y.tab.h rtn.h map.h transform.h 77 | 78 | clean: 79 | rm -f *~ *.o lex.yy.* y.* pb core lextest *.a 80 | 81 | -------------------------------------------------------------------------------- /src/check.c: -------------------------------------------------------------------------------- 1 | /* check.c acb 21-9-1994 2 | * routines for checking RTNs for undefined and unuse symbols. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "rtn.h" 8 | #include "map.h" 9 | #include "transform.h" 10 | 11 | extern pListNode transformations; 12 | 13 | /* a rule closure; the symbolic environment of a rule */ 14 | 15 | struct rule_closure { 16 | pRule rules; /* other rules */ 17 | pRule rule; /* this rule */ 18 | }; 19 | 20 | static int errors=0; 21 | 22 | static int undef_iter2(pNode a, struct rule_closure *closure) 23 | { 24 | switch(a->type) { 25 | case symbol: 26 | { 27 | if(param_indexof(closure->rule->params, a->data)==-1) { 28 | /* this node is not a parameter */ 29 | if(rule_find(closure->rules, a->data)==NULL) { 30 | fprintf(stderr, "undefined symbol '%s' in rule '%s'\n", a->data, 31 | closure->rule->symbol); 32 | errors++; 33 | }; 34 | /* check any parameters passed */ 35 | if(a->params) undef_iter2(a->params, closure); 36 | }; 37 | }; 38 | break; 39 | case mapping: 40 | { 41 | /* I have been lazy and used global variables. Please forgive me. */ 42 | if((map_lookup(mappings, a->data)==NULL) 43 | && (trans_lookup(transformations, a->data)==NULL)) { 44 | fprintf(stderr, "undefined mapping or transformation '%s' in rule '%s'\n", a->data, 45 | closure->rule->symbol); 46 | errors++; 47 | }; 48 | /* recurse into what this mapping applies to */ 49 | undef_iter2(a->params, closure); 50 | }; 51 | }; 52 | }; 53 | 54 | static int undef_iter1(pOption o, struct rule_closure *closure) 55 | { 56 | node_map(o->atoms, (NodeIterator)&undef_iter2, closure); 57 | }; 58 | 59 | static int undef_iter0(pRule r, pRule rules) 60 | { 61 | struct rule_closure closure; 62 | closure.rules = rules; 63 | closure.rule = r; 64 | option_map(r->options, (OptionIterator)&undef_iter1, &closure); 65 | }; 66 | 67 | static void check_for_undefined(pRule rules) 68 | { 69 | errors = 0; 70 | rule_inorder_traverse(rules, (RuleIterator)&undef_iter0, rules); 71 | if(errors>0) exit(1); 72 | }; 73 | 74 | static void check_for_unused(pRule rules) 75 | { 76 | }; 77 | 78 | void check_rtn(pRule rules) 79 | { 80 | check_for_undefined(rules); 81 | check_for_unused(rules); 82 | }; 83 | -------------------------------------------------------------------------------- /src/check.h: -------------------------------------------------------------------------------- 1 | /* check.c acb 21-9-1994 2 | * routines for checking RTNs for undefined and unuse symbols. 3 | */ 4 | 5 | #ifndef __CHECK_C 6 | #define __CHECK_C 7 | 8 | void check_rtn(pRule rules); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/config.h.in: -------------------------------------------------------------------------------- 1 | /* config.h.in. Generated automatically from configure.in by autoheader. */ 2 | 3 | /* Define if using alloca.c. */ 4 | #undef C_ALLOCA 5 | 6 | /* Define to empty if the keyword does not work. */ 7 | #undef const 8 | 9 | /* Define to one of _getb67, GETB67, getb67 for Cray-2 and Cray-YMP systems. 10 | This function is required for alloca.c support on those systems. */ 11 | #undef CRAY_STACKSEG_END 12 | 13 | /* Define if you have alloca, as a function or macro. */ 14 | #undef HAVE_ALLOCA 15 | 16 | /* Define if you have and it should be used (not on Ultrix). */ 17 | #undef HAVE_ALLOCA_H 18 | 19 | /* Define as __inline if that's what the C compiler calls it. */ 20 | #undef inline 21 | 22 | /* If using the C implementation of alloca, define if you know the 23 | direction of stack growth for your system; otherwise it will be 24 | automatically deduced at run-time. 25 | STACK_DIRECTION > 0 => grows toward higher addresses 26 | STACK_DIRECTION < 0 => grows toward lower addresses 27 | STACK_DIRECTION = 0 => direction of growth unknown 28 | */ 29 | #undef STACK_DIRECTION 30 | 31 | /* Define if you have the ANSI C header files. */ 32 | #undef STDC_HEADERS 33 | 34 | /* Define if you have the regcomp function. */ 35 | #undef HAVE_REGCOMP 36 | 37 | /* Define if you have the strcspn function. */ 38 | #undef HAVE_STRCSPN 39 | 40 | /* Define if you have the strdup function. */ 41 | #undef HAVE_STRDUP 42 | 43 | /* Define if you have the header file. */ 44 | #undef HAVE_UNISTD_H 45 | -------------------------------------------------------------------------------- /src/dada.c: -------------------------------------------------------------------------------- 1 | /* dada.c The user-level interface to the Dada Engine and the pb 2 | * language. 3 | * Author: Andrew C. Bulhak 4 | * Commenced: Sat Jul 8 00:28:13 1995 5 | */ 6 | 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef PREPROCESSOR 13 | #define PREPROCESSOR "cpp" 14 | #endif 15 | 16 | #ifndef PB_ENGINE 17 | #define PB_ENGINE "pb" 18 | #endif 19 | 20 | #define DIE(str) { fprintf(stderr, "%s: %s\n", argv[0], str); exit(1); } 21 | 22 | void usage(char *whoami) 23 | { 24 | fprintf(stderr, "usage: %s [options] file [file ....]\n", whoami); 25 | exit(1); 26 | }; 27 | 28 | main(int argc, char *argv[]) 29 | { 30 | int i; 31 | char **cppargv, **pbargv; 32 | int cppargc, pbargc; 33 | 34 | int pipefd[2]; 35 | int cpppid, pbpid; 36 | 37 | /* prepare arguments for the preprocessor and pb engine */ 38 | cppargv = malloc(sizeof(char *)*(argc*2+1)); 39 | cppargv[0] = PREPROCESSOR; 40 | cppargc = 1; 41 | 42 | pbargv = malloc(sizeof(char *)*argc); 43 | pbargv[0] = PB_ENGINE; 44 | pbargc = 1; 45 | 46 | /* parse arguments */ 47 | for(i=1; argv[i][0]=='-'; i++) { 48 | switch(argv[i][1]) { 49 | case 'D': /* preprocessor definition */ 50 | cppargv[cppargc++] = argv[i]; 51 | break; 52 | case 'o': /* output file */ 53 | case 'r': /* random seed */ 54 | case 's': /* start symbol */ 55 | pbargv[pbargc++] = argv[i++]; 56 | case 'd': /* dump RTN */ 57 | pbargv[pbargc++] = argv[i]; 58 | break; 59 | case '-': goto endflags; /* the following data is a sequence of 60 | filenames */ 61 | }; 62 | }; 63 | endflags: 64 | if(i>=argc) usage(argv[0]); 65 | for(;i 8 | #include 9 | #include 10 | #include 11 | 12 | #ifndef PREPROCESSOR 13 | #define PREPROCESSOR "cpp" 14 | #endif 15 | 16 | #ifndef PB_ENGINE 17 | #define PB_ENGINE "pb" 18 | #endif 19 | 20 | #define DIE(str) { fprintf(stderr, "%s: %s\n", argv[0], str); exit(1); } 21 | 22 | void usage(char *whoami) 23 | { 24 | fprintf(stderr, "usage: %s [options] file [file ....]\n", whoami); 25 | exit(1); 26 | }; 27 | 28 | main(int argc, char *argv[]) 29 | { 30 | int i; 31 | char **cppargv, **pbargv; 32 | int cppargc, pbargc; 33 | 34 | int pipefd[2]; 35 | int cpppid, pbpid; 36 | 37 | /* prepare arguments for the preprocessor and pb engine */ 38 | cppargv = malloc(sizeof(char *)*(argc*2+1)); 39 | cppargv[0] = PREPROCESSOR; 40 | cppargc = 1; 41 | 42 | pbargv = malloc(sizeof(char *)*argc); 43 | pbargv[0] = PB_ENGINE; 44 | pbargc = 1; 45 | 46 | /* parse arguments */ 47 | for(i=1; argv[i][0]=='-'; i++) { 48 | switch(argv[i][1]) { 49 | case 'D': /* preprocessor definition */ 50 | cppargv[cppargc++] = argv[i]; 51 | break; 52 | case 'o': /* output file */ 53 | case 'r': /* random seed */ 54 | case 's': /* start symbol */ 55 | pbargv[pbargc++] = argv[i++]; 56 | case 'd': /* dump RTN */ 57 | pbargv[pbargc++] = argv[i]; 58 | break; 59 | case '-': goto endflags; /* the following data is a sequence of 60 | filenames */ 61 | }; 62 | }; 63 | endflags: 64 | if(i>=argc) usage(argv[0]); 65 | for(;i 7 | 8 | static struct dictnode *nnode(char *k, void *v) 9 | { 10 | struct dictnode *n=(struct dictnode *)malloc(sizeof(struct dictnode)); 11 | n->key=k; n->value=v; n->left=n->right=NULL; 12 | return n; 13 | }; 14 | 15 | static struct dictnode *insert(struct dictnode *dn, char *k, void *val) 16 | { 17 | int c; 18 | if(!dn) return nnode(k, val); 19 | c=strcmp(k, dn->key); 20 | if(c==0) { dn->value=val; return dn; } 21 | if (c<0) { dn->left=insert(dn->left, k, val); return dn; } 22 | dn->right=insert(dn->right, k, val); return dn; 23 | }; 24 | 25 | void dict_def(pDict d, char *k, void *value) 26 | { 27 | (*d) = insert(*d, k, value); 28 | }; 29 | 30 | static struct dictnode *lookup(struct dictnode *d, char *k) 31 | { 32 | int c; 33 | if(!d) return NULL; 34 | c = strcmp(k, d->key); 35 | if(!c) return d; 36 | if(c<0) return lookup(d->left, k); 37 | return lookup(d->right, k); 38 | }; 39 | 40 | void *dict_get(Dict d, char *k) 41 | { 42 | struct dictnode *dn = lookup(d, k); 43 | return dn?dn->value:NULL; 44 | }; 45 | 46 | void dict_inorder_traverse(Dict d, traverse_fn fn, void *aux) 47 | { 48 | if(d) { 49 | dict_inorder_traverse(d->left, fn, aux); 50 | (*fn)(d->value, aux); 51 | dict_inorder_traverse(d->right, fn, aux); 52 | }; 53 | }; 54 | 55 | void dict_preorder_traverse(Dict d, traverse_fn fn, void *aux) 56 | { 57 | if(d) { 58 | (*fn)(d->value, aux); 59 | dict_inorder_traverse(d->left, fn, aux); 60 | dict_inorder_traverse(d->right, fn, aux); 61 | }; 62 | }; 63 | 64 | int dict_size(Dict d) 65 | { 66 | return d?dict_size(d->left)+dict_size(d->right)+1:0; 67 | }; 68 | 69 | void dict_free(Dict d) 70 | { 71 | if(d) { 72 | dict_free(d->left); 73 | dict_free(d->right); 74 | free(d->value); 75 | free(d); 76 | }; 77 | }; 78 | 79 | struct traverse_stamp { void *result; int todo; char *key; }; 80 | 81 | static void nth_traverse(void *v, struct traverse_stamp *s) 82 | { 83 | if(s->todo==0) { s->result=v; } 84 | s->todo--; 85 | }; 86 | 87 | void *dict_nth(Dict d, int n) 88 | { 89 | struct traverse_stamp s; 90 | s.result=NULL; s.todo = n; 91 | dict_inorder_traverse(d, (traverse_fn)nth_traverse, (void *)&s); 92 | return s.result; 93 | }; 94 | 95 | /* return the ordinal number of a key */ 96 | 97 | int dict_ord(Dict d, char *key) 98 | { 99 | int c; 100 | if(!d) return -1; 101 | c=strcmp(key, d->key); 102 | if(c==0) return dict_size(d->left); 103 | if(c<0) return dict_ord(d->left, key); 104 | return dict_size(d->left)+dict_ord(d->right, key)+1; 105 | }; 106 | -------------------------------------------------------------------------------- /src/dict.h: -------------------------------------------------------------------------------- 1 | /* dict.h acb 8-5-1995 2 | * general-purpose string-keyed associative arrays 3 | */ 4 | 5 | #ifndef __DICT_H 6 | #define __DICT_H 7 | 8 | typedef struct dictnode { 9 | char *key; 10 | void *value; 11 | struct dictnode *left, *right; 12 | } *Dict, **pDict; 13 | 14 | typedef int (*traverse_fn)(void *data, void *aux); 15 | 16 | 17 | void dict_def(pDict d, char *k, void *value); 18 | 19 | void *dict_get(Dict d, char *k); 20 | 21 | void dict_inorder_traverse(Dict d, traverse_fn fn, void *aux); 22 | 23 | void dict_preorder_traverse(Dict d, traverse_fn fn, void *aux); 24 | 25 | int dict_size(Dict d); 26 | 27 | void dict_free(Dict d); 28 | 29 | /* dictionaries have an implicit order; therefore, it makes sense to get the 30 | * nth element of a dictionary. Ordinal numbers are related to the infix 31 | * order. 32 | */ 33 | 34 | void *dict_nth(Dict d, int n); 35 | 36 | /* return the ordinal number of a key */ 37 | 38 | int dict_ord(Dict d, char *key); 39 | 40 | #endif 41 | -------------------------------------------------------------------------------- /src/dstring.c: -------------------------------------------------------------------------------- 1 | /* dstring.c acb 20-9-1994 2 | * heap-allocated dynamic strings 3 | */ 4 | 5 | #include 6 | #include 7 | 8 | /* concatenate two strings, freeing the originals */ 9 | 10 | char *dstrcat(char *a, char *b) 11 | { 12 | char *r = (char *)malloc((a?strlen(a):0)+(b?strlen(b):0)+1); 13 | strcpy(r, a?a:""); strcat(r, b?b:""); 14 | if(a)free(a); if(b)free(b); 15 | return r; 16 | }; 17 | 18 | -------------------------------------------------------------------------------- /src/dstring.h: -------------------------------------------------------------------------------- 1 | /* dstring.c acb 20-9-1994 2 | * heap-allocated dynamic strings 3 | */ 4 | 5 | #ifndef __DSTRING_C 6 | #define __DSTRING_C 7 | 8 | #ifndef __GNUC__ 9 | #define inline /* mu */ 10 | #endif 11 | 12 | /* concatenate two strings, freeing the originals */ 13 | 14 | char *dstrcat(char *a, char *b); 15 | 16 | #if 0 17 | #ifdef ULTRIX /* Ultrix has no strdup() -- yecch! */ 18 | static inline char *strdup(char *foo) 19 | { 20 | return(strcpy(malloc(strlen(foo)+1), foo)); 21 | }; 22 | 23 | #endif 24 | #endif 25 | 26 | #endif 27 | 28 | -------------------------------------------------------------------------------- /src/dump.c: -------------------------------------------------------------------------------- 1 | /* dump.c acb (9|10)-9-1994 2 | * code for dumping rules, etc. 3 | */ 4 | 5 | #include 6 | #include "rtn.h" 7 | #include "map.h" 8 | #include "transform.h" 9 | 10 | static int dump_atoms(pNode atoms); 11 | 12 | static int dump_node(pNode node) 13 | { 14 | switch(node->type) { 15 | case literal: printf("\"%s\"", node->data); break; 16 | case symbol: 17 | printf("{%s", node->data); 18 | if(node->params) { printf("("); dump_atoms(node->params); printf(")"); }; 19 | printf("}"); 20 | break; 21 | case mapping: dump_node(node->params); printf(" > %s", node->data); break; 22 | case deref: printf("DEREF("); dump_node(node->params); printf(")"); break; 23 | case var_conddef: printf("%s << ", node->data); dump_node(node->params); 24 | break; 25 | case var_def: printf("%s = ", node->data); dump_node(node->params); break; 26 | case code: printf("code:"); dump_code(node->data); break; 27 | break; 28 | }; 29 | }; 30 | 31 | static int node_iterator(pNode node, int param) 32 | { 33 | dump_node(node); printf(", "); 34 | }; 35 | 36 | static int dump_atoms(pNode atoms) 37 | { 38 | node_map(atoms, (NodeIterator)&node_iterator, NULL); 39 | }; 40 | 41 | static int option_iter(pOption opt, int param) 42 | { 43 | printf("\t\t"); dump_atoms(opt->atoms); printf("\n"); 44 | }; 45 | 46 | static void dump_options(pOption opt) 47 | { 48 | option_map(opt, (OptionIterator)&option_iter, NULL); 49 | }; 50 | 51 | void dump_params(pParam params) 52 | { 53 | if(params) { 54 | printf("%s ", params->data); 55 | dump_params(params->next); 56 | }; 57 | }; 58 | 59 | static int rule_iter(pRule r, int param) 60 | { 61 | printf("%s", r->symbol); 62 | if(r->params) { 63 | printf(" ( "); 64 | dump_params(r->params); 65 | printf(")"); 66 | }; 67 | printf(" : (%d options)\n", option_length(r->options)); 68 | dump_options(r->options); 69 | }; 70 | 71 | void dump_rules(pRule r) 72 | { 73 | rule_inorder_traverse(r, (RuleIterator)&rule_iter, NULL); 74 | }; 75 | 76 | /* 77 | * code for dumping mappings 78 | */ 79 | 80 | static void dump_mapopt(pMapOpt opt) 81 | { 82 | printf(" \"%s\" ", opt->key); 83 | switch(opt->action->mode) { 84 | case replace: 85 | printf("-> \"%s\"\n", opt->action->out); 86 | break; 87 | case subst: 88 | printf(">> \"%s\"/\"%s\"\n", opt->action->key, opt->action->out); 89 | break; 90 | default: 91 | printf("?\n"); 92 | }; 93 | }; 94 | 95 | static void dump_mapping(pMapping m) 96 | { 97 | pMapOpt o = m->options; 98 | printf("%s : \n", m->name); 99 | while(o) { 100 | dump_mapopt(o); o=o->next; 101 | }; 102 | }; 103 | 104 | void dump_mappings(pMapping m) 105 | { 106 | while(m) { 107 | dump_mapping(m); m=m->next; 108 | }; 109 | }; 110 | 111 | /* 112 | * code for dumping transformations 113 | */ 114 | 115 | static int print_param_iter(char *param, void *foo) 116 | { 117 | printf("/%s", param); 118 | }; 119 | 120 | static void dump_transcmd(pTransCmd cmd) 121 | { 122 | if(cmd->addr) { 123 | }; 124 | printf("%s", cmd->cmdname); 125 | if(cmd->params) 126 | list_mapcar(cmd->params, (ListIterator)print_param_iter, NULL); 127 | }; 128 | 129 | static int dump_transopt_iter(pTransOpt opt, void *beable) 130 | { 131 | printf(" \"%s\" -> ", opt->key); dump_transcmd(opt->cmds); putchar('\n'); 132 | }; 133 | 134 | static int dump_xform_iter(pTransformation xform, void *blah) 135 | { 136 | printf("transformation: \"%s\"\n", xform->name); 137 | list_mapcar(xform->options, (ListIterator)dump_transopt_iter, NULL); 138 | }; 139 | 140 | void dump_transformations(pListNode list) 141 | { 142 | list_mapcar(list, (ListIterator)dump_xform_iter, NULL); 143 | }; 144 | -------------------------------------------------------------------------------- /src/emit_c.c: -------------------------------------------------------------------------------- 1 | /* emit_c.c acb 35 Chs 3162 2 | * emit a RTN as C code 3 | */ 4 | 5 | #include 6 | #include 7 | #include "rtn.h" 8 | #include "map.h" 9 | #include "transform.h" 10 | 11 | #include "dstring.h" 12 | 13 | /* a structure representing state. who knows; this may need to be 14 | reentrant some day... */ 15 | 16 | struct state { 17 | FILE* of; /* output file */ 18 | int temp_count; /* number of next temporary function */ 19 | }; 20 | 21 | const char* c_prefix="dd"; 22 | 23 | /************************************************************************* 24 | * 25 | * utility functions 26 | * 27 | *************************************************************************/ 28 | 29 | /* format a string, appending it to a buffer and returning the 30 | * new value of the buffer; the old one is freed. */ 31 | 32 | static char* append(char *prev, char* fmt, ...) 33 | { 34 | char buffer[1024]; 35 | va_list args; 36 | char *r; 37 | 38 | va_start(prev, fmt); 39 | vsprintf(buffer, fmt, args); 40 | r=malloc((prev?strlen(prev):0)+strlen(buffer)+1); 41 | strcpy(r,prev?prev:""); strcat(r,buffer); 42 | if(prev)free(prev); 43 | va_end(prev); 44 | return r; 45 | } 46 | 47 | /* a standard deferred function, for lazy evaluation */ 48 | 49 | 50 | void emit_prologue(FILE* f) 51 | { 52 | fprintf(f, "/* Dada Engine C runtime prologue; acb 36 Chs 3162\ 53 | * Freely distributable\n */\n\ 54 | #include \ 55 | #include \ 56 | \ 57 | typedef char* (dfunc)();\ 58 | \ 59 | dfunc %schoose(int num, ...)\ 60 | {\ 61 | int ch=random()%num;\ 62 | dfunc df;\ 63 | va_list ap;\n\ 64 | va_start(ap, num);\ 65 | for(i=0; ioptions); 78 | struct state *st=(struct state *)l; 79 | FILE* f=st->of; 80 | char *func=NULL; /* the buffer in which the function source is 81 | built up */ 82 | 83 | func=append(func, "char* %s_%s(", c_prefix, r->symbol); 84 | /* FIXME: parameters here */ 85 | func=append(func, ")\n{\n"); 86 | if(numopts>2) { 87 | func=append(func, " return %schoose(%d, ", c_prefix, numopts); 88 | /* FIXME: enumerate options here */ 89 | /* we really need some sort of lazy evaluation mechanism */ 90 | func=append(func, " );\n"); 91 | } else { 92 | } 93 | func=append(func, "}\n\n"); 94 | fprintf(f, "%s", func); 95 | } 96 | 97 | void emit_c(FILE *f, pRule rules, pMapping mappings, 98 | pListNode transformations, char *start_sym) 99 | { 100 | struct state st; 101 | st.of=f; 102 | st.temp_count=0; 103 | 104 | emit_prologue(f); 105 | 106 | rule_inorder_traverse(rules, (RuleIterator)&c_rule_iterator, (aux_t)&st); 107 | } 108 | -------------------------------------------------------------------------------- /src/emit_ps.c: -------------------------------------------------------------------------------- 1 | /* emit_ps.c acb 11-7-1995 2 | * emit a RTN as PostScript code. 3 | */ 4 | 5 | #include 6 | #include "rtn.h" 7 | #include "map.h" 8 | #include "transform.h" 9 | 10 | #define PS_PROLOG "dadaprolog.ps" 11 | 12 | static int ps_option_iterator(pOption o, aux_t l); 13 | 14 | static void ps_xform_iterator(pListNode n, void *foo) 15 | { 16 | }; 17 | 18 | static int ps_node_iterator(pNode n, aux_t l) 19 | { 20 | FILE *f=(FILE *)l; 21 | switch(n->type) { 22 | case literal: fprintf(f, "(%s)", n->data); break; 23 | case symbol: fprintf(f, "{%s}", n->data); break; 24 | case mapping: 25 | ps_node_iterator(n->params, l); 26 | fprintf(f, " %s-map", n->data); 27 | break; 28 | case deref: ps_node_iterator(n->params, l); fprintf(f, " cvx exec"); break; 29 | case var_conddef: 30 | fprintf(f, "/%s ", n->data); 31 | ps_node_iterator(n->params, l); 32 | fprintf(f, " exec conddef"); 33 | break; 34 | case var_def: 35 | fprintf(f, "/%s ", n->data); 36 | ps_node_iterator(n->params, l); 37 | fprintf(f, " exec def"); 38 | break; 39 | case var_ref: fprintf(f, "%s", n->data); break; 40 | case code: /* FIXME */ break; 41 | case silence: ps_node_iterator(n->params, l); fprintf(f, " pop"); break; 42 | case choice: fprintf(f, "[\n"); 43 | option_map(n->data, (OptionIterator)&ps_option_iterator, l); 44 | fprintf(f, "] choose\n"); break; 45 | case star: 46 | ps_node_iterator(n->params, f); fprintf(f, " star"); 47 | break; 48 | case plus: 49 | ps_node_iterator(n->params, f); fprintf(f, " plus"); 50 | break; 51 | case repeat_const: 52 | ps_node_iterator(n->params, f); fprintf(f, " %d rep", n->int_param); 53 | break; 54 | 55 | }; 56 | }; 57 | 58 | static int ps_option_iterator(pOption o, aux_t l) 59 | { 60 | FILE *f=(FILE *)l; 61 | fprintf(f, "[\n"); 62 | node_map(o->atoms, (NodeIterator)&ps_node_iterator, l); 63 | fprintf(f, "] {exec outputstring} forall\n"); 64 | }; 65 | 66 | static int ps_rule_iterator(pRule r, aux_t l) 67 | { 68 | FILE *f=(FILE *)l; 69 | fprintf(f, "/%s{[\n", r->symbol); 70 | option_map(r->options, (OptionIterator)&ps_option_iterator, l); 71 | fprintf(f, "]choose}bind def\n"); 72 | }; 73 | 74 | void emit_ps(FILE *f, pRule rules, pMapping mappings, 75 | pListNode transformations, char *start_sym) 76 | { 77 | fprintf(f, "%%%% modify these as desired\n\ 78 | /outputstring { %% emit a string on the stack\n\ 79 | } def\n\n"); 80 | 81 | rule_inorder_traverse(rules, (RuleIterator)&ps_rule_iterator, (aux_t)f); 82 | fprintf(f, "%s\n", start_sym); 83 | }; 84 | -------------------------------------------------------------------------------- /src/lexer.x: -------------------------------------------------------------------------------- 1 | %{ 2 | /* lexer.x lexical analyser for pb, the psychobabble generator. 3 | * author: acb 4 | * commenced: 8-9-1994 5 | */ 6 | 7 | #include 8 | #include "rtn.h" 9 | #include "strfunc.h" 10 | #include "map.h" 11 | #include "transform.h" 12 | #include "machine.h" 13 | #include "y.tab.h" 14 | 15 | int cur_line = 1; 16 | char cur_file[1024]="Wibble."; /* the name of the current file */ 17 | %} 18 | 19 | %s COMMENT 20 | 21 | delim [ \t] 22 | white {delim}+ 23 | digit [0-9] 24 | integer (\-?){digit}+ 25 | real (\-?){digit}+(\.{digit}+) 26 | ident [A-Za-z_][A-Za-z0-9_\-]* 27 | 28 | %% 29 | 30 | "\n" { cur_line++; } 31 | "# "[0-9]+[^\n]* { /* the preprocessor is trying to tell us something */ 32 | sscanf(yytext+2, "%d %s", &cur_line, cur_file); 33 | cur_line--; 34 | } 35 | "#"[^\n]* { /* mu */; } 36 | "//"[^\n]* { /* mu */; } 37 | "/*" { BEGIN COMMENT; } 38 | "\n" { cur_line++; } 39 | "*/" { BEGIN 0; } 40 | [^\*\n]* /* mu */ 41 | "*" /* mu */ 42 | 43 | {white} /* mu */; 44 | {integer} { char *s=strnnew(yytext, yyleng); 45 | yylval.i = atoi(s); 46 | free(s); 47 | return(T_INTEGER); 48 | } 49 | {real} { char *s=strnnew(yytext, yyleng); 50 | yylval.f = atof(s); 51 | free(s); 52 | return(T_NUM); 53 | } 54 | \"[^\"]*(\\.[^\"]*)*\" { /* return a literal */ 55 | yylval.s = strnnew(yytext+1, yyleng-2); 56 | cookstr(yylval.s); 57 | return T_LITERAL; 58 | }; 59 | "%trans" { return T_XFORM; /* transformation indicator */ }; 60 | "%cond" { return T_COND; /* conditional evaluation indicator */ }; 61 | "%exists" 62 | "%E" 63 | "%e" { return T_EXISTS; /* existential predicate */ }; 64 | "%num" 65 | "%N" 66 | "%n" { return T_NUM; /* number function */ }; 67 | "%repeat" { return T_REPEAT; }; 68 | "%unique" { return T_UNIQUE; /* uniqueness directive */ }; 69 | "%enum" { return T_ENUM; /* enumeration directive */ }; 70 | "%pick" { return T_PICK; /* enumeration directive */ }; 71 | "%resource" { return T_RESOURCE; /* prepended to non-startable rule */ }; 72 | {ident} { /* return the identifier */ 73 | yylval.s = strnnew(yytext, yyleng); 74 | return(T_IDENT); } 75 | "->" { return('M'); /* for "Mapping" */ } 76 | "<->" { return('R'); /* for "Reversible mapping" */ } 77 | "<<" { return('V'); /* for "variable definition" (also choose lesser) */ } 78 | ">>" { return('G'); /* for "greater" */ } 79 | "@" { return(T_DEREF); } 80 | ".." { return(T_ELLIPSIS); } 81 | [\|=;:\(\)\,\[\]\{\}\$\>\/\*\+\-\<\%\?] return(*yytext); 82 | 83 | %% 84 | 85 | #ifndef yywrap 86 | /* GNU flex doesn't need a yywrap() to be defined; lex (at least the lex from 87 | DEC ULTRIX) does. */ 88 | int yywrap() { return 1; } 89 | #endif/ 90 | -------------------------------------------------------------------------------- /src/lextest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "rtn.h" 3 | #include "map.h" 4 | #include "transform.h" 5 | #include "y.tab.h" 6 | 7 | YYSTYPE yylval; 8 | 9 | main() { 10 | int i; 11 | while(i=yylex()) { 12 | printf("lexer returns (%i) ", i); 13 | switch(i) { 14 | case T_LITERAL: 15 | printf("literal text: <%s>", yylval); 16 | break; 17 | case T_IDENT: 18 | printf("identifier: <%s>", yylval); 19 | break; 20 | }; 21 | putchar('\n'); 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /src/limits.h: -------------------------------------------------------------------------------- 1 | /* limits.h Limits for aspects of the pb language. 2 | * Author: Andrew C. Bulhak 3 | * Commenced: Mon Jul 17 00:48:49 1995 4 | */ 5 | 6 | #ifndef __LIMITS_H 7 | #define __LIMITS_H 8 | 9 | /* Maximum number of options to be selected from in a single choice */ 10 | 11 | #define MAX_OPTIONS 256 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/machine.c: -------------------------------------------------------------------------------- 1 | /* machine.c acb 14-2-1995 2 | * the embedded imperative code interpreter in pb 3 | * A lot of stuff lifted from rml, also by acb so it's Allowed. 4 | */ 5 | 6 | #include 7 | #include 8 | 9 | #include "variables.h" 10 | #include "machine.h" 11 | #include "strfunc.h" 12 | #include "rtn.h" 13 | #include "resolve.h" 14 | 15 | #ifndef min 16 | #define min(a,b) (((a)<(b))?(a):(b)) 17 | #endif 18 | 19 | #ifndef max 20 | #define max(a,b) (((a)>(b))?(a):(b)) 21 | #endif 22 | 23 | #define STACK_SIZE 1024 24 | 25 | static Cell stack[STACK_SIZE]; 26 | static int sp=0; 27 | 28 | extern pRule rule_base; 29 | 30 | static inline void push(pCell c) { stack[sp++]=*c; }; 31 | /* temp_pop is thusly named because it returns a pointer whose contents will 32 | be later reclaimed */ 33 | static inline pCell temp_pop() { return &(stack[--sp]); } 34 | 35 | static inline void push_int(int i) 36 | { 37 | stack[sp].type = int_t; stack[sp++].contents.i=i; 38 | }; 39 | 40 | static inline void push_str(char *s) 41 | { 42 | stack[sp].type = string_t; stack[sp++].contents.s=s; 43 | }; 44 | 45 | /* find last instruction in list */ 46 | 47 | pInstr last(pInstr a) 48 | { 49 | if(a==NULL) return NULL; 50 | if(a->next==NULL) return a; 51 | return last(a->next); 52 | }; 53 | 54 | static inline char *exec_instr(pInstr s) 55 | { 56 | pCell tc, tc2; 57 | char buffer[16]; 58 | 59 | switch(s->opcode) { 60 | case SET: 61 | /* operand must be a string */ 62 | tc=temp_pop(); 63 | switch(tc->type) { 64 | case string_t: 65 | var_put(s->operand.contents.s, tc->contents.s); 66 | break; 67 | case int_t: 68 | var_put_int(s->operand.contents.s, tc->contents.i); 69 | break; 70 | }; 71 | break; 72 | case EMIT: 73 | tc=temp_pop(); 74 | switch(tc->type) { 75 | case string_t: return tc->contents.s; 76 | case int_t: sprintf(buffer, "%i", tc->contents.i); 77 | return strdup(buffer); 78 | }; 79 | case PUSHV: 80 | { 81 | struct var *v=var_lookup(vars, s->operand.contents.s); 82 | switch(v->type) { 83 | case string_t: 84 | push_str(v->value.s); 85 | break; 86 | case int_t: 87 | push_int(v->value.i); 88 | break; 89 | }; 90 | } 91 | break; 92 | case INVOKE: 93 | { 94 | pRule r=rule_find(rule_base, s->operand.contents.s); 95 | if(r) { 96 | push_str(resolve_rule(rule_base, r)); 97 | } else { 98 | fprintf(stderr, "attempted to invoke non-existent rule \"%s\" in expression.\n", s->operand.contents.s); 99 | push_str(NULL); 100 | }; 101 | } 102 | break; 103 | case PUSH: 104 | switch(s->operand.type) { 105 | case string_t: 106 | push_str(strdup(s->operand.contents.s)); 107 | break; 108 | case int_t: 109 | push_int(s->operand.contents.i); 110 | break; 111 | }; 112 | break; 113 | case ADD: 114 | tc=temp_pop(); 115 | tc2=temp_pop(); 116 | if((tc->type==int_t)&&(tc2->type==int_t)) { 117 | push_int(tc->contents.i+tc2->contents.i); 118 | } else { 119 | char *s0, *s1; 120 | /* string concatenation */ 121 | s0=((tc->type==int_t)?itoa(tc->contents.i):(tc->contents.s)); 122 | s1=((tc2->type==int_t)?itoa(tc2->contents.i):(tc2->contents.s)); 123 | push_str(concat(s1, s0)); free(s0); free(s1); 124 | }; 125 | break; 126 | case SUB: 127 | tc=temp_pop(); 128 | tc2=temp_pop(); 129 | if((tc->type==int_t)&&(tc2->type==int_t)) { 130 | push_int(tc2->contents.i+tc->contents.i); 131 | }; 132 | break; 133 | case MUL: 134 | tc=temp_pop(); 135 | tc2=temp_pop(); 136 | if((tc->type==int_t)&&(tc2->type==int_t)) { 137 | push_int(tc->contents.i*tc2->contents.i); 138 | }; 139 | break; 140 | case DIV: 141 | tc=temp_pop(); 142 | tc2=temp_pop(); 143 | if((tc->type==int_t)&&(tc2->type==int_t)) { 144 | push_int(tc2->contents.i/tc->contents.i); 145 | }; 146 | break; 147 | case MOD: 148 | tc=temp_pop(); 149 | tc2=temp_pop(); 150 | if((tc->type==int_t)&&(tc2->type==int_t)) { 151 | push_int(tc2->contents.i%tc->contents.i); 152 | }; 153 | break; 154 | case RANDOM: 155 | tc2=temp_pop(); 156 | tc=temp_pop(); 157 | if((tc->type==int_t)&&(tc2->type==int_t)) { 158 | push_int((random()%(tc2->contents.i-tc->contents.i+1)) 159 | +tc->contents.i); 160 | }; 161 | break; 162 | case LESSER: 163 | tc2=temp_pop(); 164 | tc=temp_pop(); 165 | if((tc->type==int_t)&&(tc2->type==int_t)) { 166 | push_int(min(tc->contents.i, tc2->contents.i)); 167 | }; 168 | break; 169 | case GREATER: 170 | tc2=temp_pop(); 171 | tc=temp_pop(); 172 | if((tc->type==int_t)&&(tc2->type==int_t)) { 173 | push_int(max(tc->contents.i, tc2->contents.i)); 174 | }; 175 | break; 176 | }; 177 | return NULL; 178 | }; 179 | 180 | /* execute a stream of instructions, possibly returning a string */ 181 | 182 | char *exec_stream(pInstr s) 183 | { 184 | while(s) { 185 | char *r; 186 | if(r=exec_instr(s)) return r; 187 | s=s->next; 188 | }; 189 | return NULL; 190 | }; 191 | 192 | char *opname[]= { 193 | "SET", "PUSHV", "PUSH", "ADD", "SUB", "MUL", "DIV", "EMIT", "INVOKE" 194 | }; 195 | 196 | void dump_code(pInstr s) 197 | { 198 | while(s) { 199 | printf("%s ", opname[s->opcode]); 200 | switch(s->operand.type) { 201 | case int_t: printf("%i\n", s->operand.contents.i); break; 202 | case string_t: printf("\"%s\"\n", s->operand.contents.s); break; 203 | default: putchar('\n'); 204 | }; 205 | s=s->next; 206 | }; 207 | }; 208 | -------------------------------------------------------------------------------- /src/machine.h: -------------------------------------------------------------------------------- 1 | /* machine.h acb 14-2-1995 2 | * the embedded imperative code interpreter in pb 3 | * A lot of stuff lifted from rml, also by acb so it's Allowed. 4 | */ 5 | 6 | #ifndef __MACHINE_H 7 | #define __MACHINE_H 8 | 9 | #include 10 | #include "variables.h" 11 | 12 | #ifndef __GNU__ 13 | #define inline /* blah */ 14 | #endif 15 | 16 | typedef struct { 17 | type_t type; 18 | union { 19 | int i; 20 | char *s; 21 | } contents; 22 | } Cell, *pCell; 23 | 24 | enum opcode { 25 | SET, /* pop stack, setting variable */ 26 | PUSHV, /* push variable onto stack */ 27 | PUSH, /* push some sort of literal value */ 28 | ADD, /* add or concatenate */ 29 | SUB, 30 | MUL, 31 | DIV, 32 | EMIT, /* pop stack and exit, returning result */ 33 | INVOKE, /* invoke a rule, pushing its output onto the stack */ 34 | MOD, 35 | RANDOM, /* generate a random number */ 36 | LESSER, /* select the lesser of two evils^H^H^H^H^Hnumbers */ 37 | GREATER 38 | }; 39 | 40 | typedef struct tagInstr { 41 | enum opcode opcode; 42 | Cell operand; 43 | struct tagInstr *next; 44 | } Instr, *pInstr; 45 | 46 | /* manipulate instruction lists */ 47 | 48 | pInstr last(pInstr a); 49 | 50 | static inline pInstr icat(pInstr a, pInstr b) 51 | { 52 | if(a) { 53 | pInstr l = last(a); 54 | l->next = b; 55 | return a; 56 | } else return b; 57 | }; 58 | 59 | /* return a simple instruction */ 60 | static inline pInstr e_simple(enum opcode op) 61 | { 62 | pInstr result = (pInstr) malloc(sizeof(Instr)); 63 | result->opcode = op; 64 | result->operand.type = mu; /* nothing */ 65 | result->next = NULL; 66 | return result; 67 | }; 68 | 69 | static inline pInstr e_set(char *name) 70 | { 71 | pInstr result = e_simple(SET); 72 | result->operand.type = string_t; 73 | result->operand.contents.s = name; 74 | return result; 75 | }; 76 | 77 | static inline pInstr e_pushv(char *name) 78 | { 79 | pInstr result = e_simple(PUSHV); 80 | result->operand.type = string_t; 81 | result->operand.contents.s = name; 82 | return result; 83 | }; 84 | 85 | static inline pInstr e_push_int(int i) 86 | { 87 | pInstr result = e_simple(PUSH); 88 | result->operand.type = int_t; 89 | result->operand.contents.i = i; 90 | return result; 91 | }; 92 | 93 | static inline pInstr e_push_str(char *s) 94 | { 95 | pInstr result = e_simple(PUSH); 96 | result->operand.type = string_t; 97 | result->operand.contents.s = s; 98 | return result; 99 | }; 100 | 101 | static inline pInstr e_invoke(char *name) 102 | { 103 | pInstr result = e_simple(INVOKE); 104 | result->operand.type = string_t; 105 | result->operand.contents.s = name; 106 | return result; 107 | }; 108 | 109 | char *exec_stream(pInstr s); 110 | 111 | void dump_code(pInstr s); 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /src/map.c: -------------------------------------------------------------------------------- 1 | /* map.c acb 23-9-1994 2 | * mapping support for pb 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include /* regex.h seems to need this */ 9 | #include "config.h" 10 | #include /* the POSIX.2 regular expression functions */ 11 | #include "map.h" 12 | 13 | 14 | pMapping mappings = NULL; 15 | 16 | 17 | pMapAction new_replace_action(char *out) 18 | { 19 | pMapAction r = (pMapAction) malloc(sizeof(MapAction)); 20 | r->mode = replace; r->out = out; 21 | return r; 22 | }; 23 | 24 | pMapAction new_subst_action(char *key, char *out) 25 | { 26 | pMapAction r = (pMapAction) malloc(sizeof(MapAction)); 27 | r->mode = subst; r->key=key; r->out = out; 28 | return r; 29 | }; 30 | 31 | pMapOpt mapopt_concat(pMapOpt a, pMapOpt b) 32 | { 33 | pMapOpt r = a; 34 | while(a->next) a=a->next; 35 | a->next = b; 36 | return r; 37 | }; 38 | 39 | pMapOpt mapopt_cons(char *key, pMapAction act, pMapOpt cdr) 40 | { 41 | pMapOpt r = (pMapOpt) malloc(sizeof(MapOpt)); 42 | r->key = key; 43 | r->action = act; 44 | r->next = cdr; 45 | return r; 46 | }; 47 | 48 | /* match an option to a string, using regular expressions (ooh!) */ 49 | pMapOpt mapopt_match(pMapOpt list, char *string) 50 | { 51 | while(list) { 52 | regex_t key_regex; 53 | regmatch_t match; 54 | 55 | regcomp(&key_regex, list->key, 0); 56 | 57 | if(regexec(&key_regex, string, 1, &match, 0)==0) { 58 | regfree(&key_regex); 59 | return list; 60 | }; 61 | 62 | regfree(&key_regex); 63 | list=list->next; 64 | }; 65 | return NULL; 66 | }; 67 | 68 | pMapping map_cons(char *n, pMapOpt opts, pMapping cdr) 69 | { 70 | pMapping r = (pMapping) malloc(sizeof(Mapping)); 71 | r->name = n; 72 | r->options = opts; 73 | r->next = cdr; 74 | return r; 75 | }; 76 | 77 | pMapping map_lookup(pMapping list, char *name) 78 | { 79 | return((list)?((strcmp(list->name, name)==0)?list: 80 | map_lookup(list->next, name)):NULL); 81 | }; 82 | 83 | /* apply_mapping() applies a mapping to a string. The input is assumed to 84 | * be heap-allocated, and is either returned unchanged or deallocated. 85 | * The output is heap-allocated. 86 | */ 87 | 88 | char *regex_subst(char *in, char *from, char *to) 89 | { 90 | char *r; 91 | regex_t re; 92 | regmatch_t match; 93 | int len; 94 | int error; 95 | int offset = 0; 96 | 97 | /* check for special cases: prepend and append */ 98 | if(strcmp(from, "^")==0) { 99 | r = (char *)malloc(strlen(in)+strlen(to)+1); 100 | strcpy(r, to); strcat(r, in); 101 | return r; 102 | }; 103 | if(strcmp(from, "$")==0) { 104 | r = (char *)malloc(strlen(in)+strlen(to)+1); 105 | strcpy(r, in); strcat(r, to); 106 | return r; 107 | }; 108 | 109 | if(regcomp(&re, from, 0)!=0) return NULL; 110 | 111 | /* first, accrue the length of the resulting string */ 112 | len = strlen(in); 113 | 114 | error = regexec(&re, in+offset, 1, &match, 0); 115 | 116 | while(!error) { 117 | len += strlen(to)-(match.rm_eo-match.rm_so); 118 | if(match.rm_eo==0) break; 119 | offset+=match.rm_eo; 120 | error = regexec(&re, in+offset, 1, &match, REG_NOTBOL); 121 | }; 122 | 123 | /* now, composite the resulting string */ 124 | offset = 0; 125 | r = (char *) malloc(len+1); *r = '\0'; 126 | 127 | error = regexec(&re, in+offset, 1, &match, 0); 128 | strncat(r, in+offset, match.rm_so); 129 | 130 | while(!error) { 131 | strcat(r, to); 132 | if(match.rm_eo==0) break; 133 | offset += match.rm_eo; 134 | error = regexec(&re, in+offset, 1, &match, 0); 135 | /* fprintf(stderr, "match.rm_so: %d, match.rm_eo: %d\n", 136 | match.rm_so, match.rm_eo);*/ 137 | if (error) strcat(r, in+offset); 138 | else strncat(r, in+offset, match.rm_so); 139 | }; 140 | return r; 141 | }; 142 | 143 | char *apply_mapping(char *input, pMapping m) 144 | { 145 | pMapOpt option; 146 | 147 | if(!m) return input; 148 | 149 | option = mapopt_match(m->options, input); 150 | 151 | if(!option) return input; /* by default, let it be */ 152 | 153 | switch(option->action->mode) { 154 | case replace: 155 | free(input); 156 | return(strdup(option->action->out)); 157 | case subst: 158 | /* here we need to do regex substitution. Ooh, tricky! */ 159 | { 160 | char *r = regex_subst(input, option->action->key, option->action->out); 161 | if(!r) return input; /* failed */ 162 | free(input); 163 | return r; 164 | }; 165 | }; 166 | }; 167 | -------------------------------------------------------------------------------- /src/map.h: -------------------------------------------------------------------------------- 1 | /* map.h acb 23-9-1994 2 | * mapping support for pb 3 | */ 4 | 5 | #ifndef __MAP_H 6 | #define __MAP_H 7 | 8 | /* an action performed on a string if it matches a key */ 9 | 10 | enum mapmode { 11 | replace, /* completely replace the input string with another string */ 12 | subst /* perform an ed-style regular expression substitution */ 13 | }; 14 | 15 | typedef struct tagMapAction { 16 | enum mapmode mode; 17 | char *out; /* replacement/substitution text */ 18 | char *key; /* key for substitution; substring matching key is replaced. 19 | replacement is equivalent to substitution with key ".*" */ 20 | } MapAction, *pMapAction; 21 | 22 | /* one option in a mapping */ 23 | 24 | typedef struct tagMapOpt { 25 | char *key; /* key (regular expression) to match input against */ 26 | pMapAction action; 27 | struct tagMapOpt *next; 28 | } MapOpt, *pMapOpt; 29 | 30 | typedef struct tagMapping { 31 | char *name; 32 | pMapOpt options; 33 | struct tagMapping *next; 34 | } Mapping, *pMapping; 35 | 36 | /* 37 | * e x t e r n a l v a r i a b l e s 38 | */ 39 | 40 | extern pMapping mappings; 41 | 42 | /* 43 | * p r o t o t y p e s f o l l o w 44 | */ 45 | 46 | pMapAction new_replace_action(char *out); 47 | 48 | pMapAction new_subst_action(char *key, char *out); 49 | 50 | pMapOpt mapopt_concat(pMapOpt a, pMapOpt b); 51 | 52 | pMapOpt mapopt_cons(char *key, pMapAction act, pMapOpt cdr); 53 | 54 | /* match an option to a string, using regular expressions (ooh!) */ 55 | pMapOpt mapopt_match(pMapOpt list, char *string); 56 | 57 | pMapping map_cons(char *n, pMapOpt opts, pMapping cdr); 58 | 59 | pMapping map_lookup(pMapping list, char *name); 60 | 61 | /* 62 | * f u n c t i o n s f o r a p p l y i n g m a p p i n g s 63 | */ 64 | 65 | /* apply_mapping() applies a mapping to a string. The input is assumed to 66 | * be heap-allocated, and is either returned unchanged or deallocated. 67 | * The output is heap-allocated. 68 | */ 69 | 70 | char *apply_mapping(char *input, pMapping m); 71 | 72 | #endif 73 | 74 | -------------------------------------------------------------------------------- /src/parser.y: -------------------------------------------------------------------------------- 1 | /* parser.y yacc script for the parser for pb, the programmable 2 | * psychobabble generator. 3 | * author: acb 4 | * commenced: 8-9-1994 5 | * 6 | * 28-9-1994: Started adding grammatical elements for sed-style 7 | * transformations 8 | * 10-2-1995: Started adding in conditional evaluation primitives 9 | * 14-2-1995: Started adding in embedded imperative code 10 | * 13-5-1995: Started adding in regular expression-style syntactic 11 | * features, such as the Kleene star. 12 | * 4-7-1995: Got the repeat operator working 13 | */ 14 | 15 | %{ 16 | 17 | #include 18 | #include /* NULL */ 19 | #include 20 | #include "rtn.h" 21 | #include "check.h" 22 | #include "map.h" 23 | #include "transform.h" 24 | #include "machine.h" 25 | #include "ptrlist.h" 26 | 27 | #define YYERROR_VERBOSE 1 28 | #define YYDEBUG 1 29 | 30 | pRule initial_rule=NULL; 31 | 32 | #ifndef YYBISON 33 | int yydebug=0; 34 | #endif 35 | 36 | pListNode transformations = NULL; 37 | extern int verbose; 38 | 39 | extern void use_rtn(pRule rtn); 40 | 41 | %} 42 | 43 | %union { 44 | double f; 45 | int i; 46 | char *s; 47 | pNode n; 48 | pOption o; 49 | pRule r; 50 | pParam p; /* superceded; pListNode is a generic list of pointer-sized 51 | scalar quantities */ 52 | pListNode l; 53 | pMapAction ma; 54 | pMapOpt mo; 55 | int *pi; 56 | pTransCmd tc; 57 | pTransOpt to; 58 | pTransformation tr; 59 | pInstr c; 60 | } 61 | 62 | %token T_XFORM 63 | %token T_COND 64 | 65 | %token T_EXISTS 66 | %token T_NUM 67 | %token T_REPEAT 68 | %token T_UNIQUE 69 | %token T_ENUM 70 | %token T_PICK 71 | %token T_RESOURCE 72 | 73 | %token T_LITERAL 74 | %token T_IDENT 75 | %token T_NUM 76 | %token T_INTEGER 77 | 78 | %type rules 79 | %type rule 80 | %type options 81 | %type option 82 | %type atoms 83 | %type atom 84 | %type atom2 85 | %type

params 86 | %type mapopt 87 | %type mapopts 88 | %type mapaction 89 | %type transaddr 90 | %type translist 91 | %type transcmd 92 | %type transopt 93 | %type transopts 94 | 95 | %type imperatives 96 | %type imperative 97 | %type expr 98 | 99 | %right '?' 100 | %right T_DEREF 101 | %left '>' 102 | 103 | %left T_ELLIPSIS 104 | %left 'V' 'G' 105 | %left '-' '+' 106 | %left '*' '/' '%' 107 | %right T_UNIQUE T_ENUM T_PICK 108 | 109 | %% 110 | 111 | input: rules { use_rtn($1); 112 | /* if(dump_rtn) { 113 | dump_rules($1); 114 | dump_mappings(mappings); 115 | dump_transformations(transformations); 116 | } 117 | check_rtn($1); 118 | rule_base = $1; 119 | if(start_symbol) { 120 | initial_rule=rule_find($1, start_symbol); 121 | if(!initial_rule) { 122 | fprintf(stderr, "rule \"%s\" does not exist.\n", 123 | start_symbol); 124 | exit(1); 125 | }; 126 | }; 127 | if(!inhibit) fprintf(outfile, "%s\n", 128 | resolve_rule($1, initial_rule)); */} 129 | ; 130 | 131 | rules: /* mu */ { $$ = NULL; } 132 | | rules rule { 133 | /* if(initial_rule==NULL) { 134 | initial_rule = $2; 135 | if(verbose)fprintf(stderr, "Start symbol == %s\n", 136 | initial_rule->symbol); 137 | };*/ 138 | /* FIXME: add check for duplicate rules here */ 139 | $$ = rule_insert($1, $2); 140 | } 141 | | rules mapping { $$ = $1; /* mappings != rules */ } 142 | | rules transformation { $$ = $1; /* mappings != rules */ } 143 | ; 144 | 145 | rule: T_IDENT ':' options ';' { pRule r = rule_new($1, $3, NULL); 146 | if(initial_rule==NULL) { 147 | initial_rule = r; 148 | if(verbose) 149 | fprintf(stderr, "Start symbol == %s\n", 150 | r->symbol); 151 | }; 152 | $$ = r; 153 | } 154 | | T_RESOURCE T_IDENT ':' options ';' { pRule r = rule_new($2, $4, NULL); 155 | $$ = r; 156 | } 157 | | T_IDENT '(' params ')' ':' options ';' { pRule r = rule_new($1, $6, $3); 158 | $$ = r; 159 | } 160 | ; 161 | 162 | transformation: T_XFORM T_IDENT ':' transopts ';' { 163 | transformations = list_cons(new_transformation($2, $4), transformations); 164 | /* fprintf(stderr, "Transformation: %s\n", 165 | ((pTransformation)transformations->data)->name);*/ 166 | } 167 | ; 168 | 169 | transopts: transopt transopts { $$ = list_cons($1, $2); }; 170 | | transopt { $$ = list_cons($1, NULL); } 171 | ; 172 | 173 | transopt: T_LITERAL ':' transcmd { $$ = new_transopt($1, $3); 174 | /* fprintf(stderr, "xform option: %s", $1);*/ 175 | } 176 | ; 177 | 178 | transcmd: transaddr T_IDENT translist ';' { $$ = new_transcmd($1, $2, $3); } 179 | ; 180 | 181 | transaddr: T_INTEGER { $$ = new_addr_range($1, $1); } 182 | | T_INTEGER ',' T_INTEGER { $$ = new_addr_range($1, $3); } 183 | | /* mu */ { $$ = NULL; } 184 | ; 185 | 186 | translist: T_LITERAL translist { $$ = list_cons((void *)$1, $2); } 187 | | { $$ = NULL; } 188 | ; 189 | 190 | mapping: T_IDENT ':' mapopts ';' { mappings = map_cons($1, $3, mappings); } 191 | ; 192 | 193 | mapopts: mapopts mapopt { $$ = mapopt_concat($1, $2); } 194 | | mapopt { $$ = $1; } 195 | ; 196 | 197 | mapopt: T_LITERAL 'M' mapaction { $$ = mapopt_cons($1, $3, NULL); } 198 | | T_LITERAL 'R' T_LITERAL { 199 | $$ = mapopt_cons($1, new_replace_action($3), 200 | mapopt_cons($3, new_replace_action($1), NULL)); 201 | } 202 | ; 203 | 204 | mapaction: T_LITERAL { $$ = new_replace_action($1); } 205 | | T_LITERAL '/' T_LITERAL { $$ = new_subst_action($1, $3); } 206 | ; 207 | 208 | params: params T_IDENT { $$ = list_append($1, list_cons((void *)$2, NULL)); } 209 | | T_IDENT { $$ = list_cons((void *)$1, NULL); } 210 | ; 211 | 212 | options: option '|' options { $$ = option_append($1, $3); } 213 | | option { $$ = $1; } 214 | ; 215 | 216 | option: atoms { $$ = option_cons($1, NULL); } 217 | ; 218 | 219 | atoms: atoms atom { $$ = node_append($1, $2); } 220 | | atom { $$ = $1; } 221 | ; 222 | 223 | atom: atom2 { $$ = $1; } 224 | | atom '>' T_IDENT { pNode n = node_cons(mapping, $3, NULL); 225 | n->params = $1; 226 | $$ = n; 227 | } 228 | | T_DEREF atom { pNode n = node_cons(deref, NULL, NULL); 229 | n->params=$2; $$=n; } 230 | | T_IDENT 'V' atom { pNode n = node_cons(var_conddef, $1, NULL); 231 | n->params = $3; 232 | $$ = n; 233 | } 234 | | T_IDENT '=' atom { pNode n = node_cons(var_def, $1, NULL); 235 | n->params = $3; 236 | $$ = n; 237 | } 238 | | '$' T_IDENT { $$ = node_cons(var_ref, $2, NULL); } 239 | | '{' imperatives '}' { $$ = node_cons(code, (char *)$2, NULL); } 240 | | '?' atom { pNode n = node_cons(silence, NULL, NULL); n->params=$2; 241 | $$ = n; } 242 | | atom '*' { pNode n = node_cons(star, NULL, NULL); n->params=$1; $$=n; } 243 | | atom '+' { pNode n = node_cons(plus, NULL, NULL); n->params=$1; $$=n; } 244 | | '[' options ']' { pNode n = node_cons(choice, (char *)$2, NULL); 245 | n->last_choice = -1; $$=n; } 246 | | T_REPEAT '(' atom ',' T_INTEGER ')' { 247 | pNode n = node_cons(repeat_const, NULL, NULL); 248 | n->params = $3; n->int_param = $5; 249 | $$=n; } 250 | | T_REPEAT '(' atom ',' T_IDENT ')' { 251 | pNode n = node_cons(repeat_var, NULL, NULL); 252 | n->params = $3; n->data = $5; 253 | $$=n; } 254 | | T_UNIQUE atom { pNode n=$2; n->mode = unique; $$=n; } 255 | | T_ENUM atom { pNode n=$2; n->mode = enumerate; $$=n; } 256 | | T_PICK '(' T_INTEGER ',' atom ')' { pNode n=$5; n->mode = pick; 257 | n->pick_num=$3; $$=n; } 258 | ; 259 | 260 | atom2: T_LITERAL { $$ = node_cons(literal, $1, NULL); } 261 | | T_IDENT { $$ = node_cons(symbol, $1, NULL); } 262 | | T_IDENT '(' atoms ')' { pNode n = node_cons(symbol, $1, NULL); 263 | n->params = $3; 264 | $$ = n; 265 | } 266 | ; 267 | 268 | 269 | imperatives: { $$ = NULL; } 270 | | imperative { $$ = $1; } 271 | | imperatives ';' imperative { $$ = icat($1, $3); } 272 | ; 273 | 274 | imperative: T_IDENT '=' expr { $$ = icat($3, e_set($1)); } 275 | | '=' expr { $$ = icat($2, e_simple(EMIT)); } 276 | ; 277 | 278 | expr: T_INTEGER { $$ = e_push_int($1); } 279 | | T_LITERAL { $$ = e_push_str($1); } 280 | | T_IDENT { $$ = e_pushv($1); } 281 | | T_DEREF T_IDENT { $$ = e_invoke($2); } 282 | | '(' expr ')' { $$ = $2; } 283 | | expr '+' expr { $$ = icat($1, icat($3, e_simple(ADD))); } 284 | | expr '-' expr { $$ = icat($1, icat($3, e_simple(SUB))); } 285 | | expr '*' expr { $$ = icat($1, icat($3, e_simple(MUL))); } 286 | | expr '/' expr { $$ = icat($1, icat($3, e_simple(DIV))); } 287 | | expr '%' expr { $$ = icat($1, icat($3, e_simple(MOD))); } 288 | | expr T_ELLIPSIS expr { $$ = icat($1, icat($3, e_simple(RANDOM))); } 289 | | expr 'V' expr { $$ = icat($1, icat($3, e_simple(LESSER))); } 290 | | expr 'G' expr { $$ = icat($1, icat($3, e_simple(GREATER))); } 291 | ; 292 | 293 | %% 294 | 295 | extern int cur_line; 296 | extern char cur_file[1024]; 297 | 298 | yyerror(char *s) 299 | { 300 | fprintf(stderr, "%s:%i: %s\n", cur_file, cur_line, s); 301 | }; 302 | 303 | #if 0 304 | 305 | int strtoseed(char *s) 306 | { 307 | int r=0; 308 | if(atoi(s))return atoi(s); 309 | while(*s) { r+=*(s++); } 310 | return r; 311 | }; 312 | 313 | main(int argc, char *argv[]) 314 | { 315 | int i; 316 | 317 | char *rseed=NULL; /* a random seed, in string form */ 318 | 319 | for(i=1; i 7 | #include 8 | #include "rtn.h" 9 | #include "check.h" 10 | #include "map.h" 11 | #include "transform.h" 12 | 13 | static char *start_symbol = NULL; /* to override the default start symbol */ 14 | pRule rule_base; 15 | extern pRule initial_rule; 16 | int dump_rtn=0, inhibit=0, verbose=0, trace=0, old_probability=0, wrapwidth=80; 17 | FILE *outfile; 18 | extern int yydebug; 19 | 20 | 21 | /* resolve a RTN */ 22 | void use_rtn(pRule rtn) 23 | { 24 | if(!rtn) return; 25 | 26 | if(dump_rtn) { 27 | dump_rules(rtn); 28 | dump_mappings(mappings); 29 | dump_transformations(transformations); 30 | } 31 | check_rtn(rtn); 32 | rule_base = rtn; 33 | if(start_symbol) { 34 | initial_rule=rule_find(rtn, start_symbol); 35 | if(!initial_rule) { 36 | fprintf(stderr, "rule \"%s\" does not exist.\n", 37 | start_symbol); 38 | exit(1); 39 | }; 40 | }; 41 | if(!inhibit) 42 | if(wrapwidth) { 43 | print_wrapped(outfile, resolve_rule(rtn, initial_rule), wrapwidth); 44 | putc('\n', outfile); 45 | } else 46 | fprintf(outfile, "%s\n", resolve_rule(rtn, initial_rule)); 47 | }; 48 | 49 | int strtoseed(char *s) 50 | { 51 | int r=0; 52 | if(atoi(s))return atoi(s); 53 | while(*s) { r+=*(s++); } 54 | return r; 55 | }; 56 | 57 | main(int argc, char *argv[]) 58 | { 59 | int i; 60 | char *p; 61 | 62 | char *rseed=NULL; /* a random seed, in string form */ 63 | 64 | outfile = stdout; 65 | 66 | /* read environment variables as needed */ 67 | if(p=getenv("COLUMNS")) wrapwidth=atoi(p); 68 | 69 | /* check command-line arguments */ 70 | 71 | for(i=1; i 6 | #include "rtn.h" 7 | #include "check.h" 8 | #include "map.h" 9 | #include "transform.h" 10 | 11 | char *start_symbol = NULL; /* to override the default start symbol */ 12 | pRule rule_base; 13 | extern pRule initial_rule; 14 | FILE *outfile=stdout; 15 | int dump_rtn=0, inhibit=0, verbose=0, trace=0, old_probability=0; 16 | 17 | void use_rtn(pRule rtn) 18 | { 19 | /* emit_ps(outfile, rtn, mappings, transformations, 20 | (start_symbol)?start_symbol:initial_rule->symbol);*/ 21 | emit_c(outfile, rtn, mappings, transformations, 22 | (start_symbol)?start_symbol:initial_rule->symbol); 23 | }; 24 | 25 | main(int argc, char *argv[]) 26 | { 27 | int i; 28 | for(i=1; i 6 | #include "ptrlist.h" 7 | 8 | pListNode list_append(pListNode a, pListNode b) 9 | { 10 | pListNode r = a; 11 | 12 | if(!a) return b; 13 | while(a->next) a=a->next; 14 | a->next = b; 15 | return r; 16 | }; 17 | 18 | pListNode list_cons(void *data, pListNode next) 19 | { 20 | pListNode r = (pListNode) malloc(sizeof(ListNode)); 21 | r->data = data; r->next = next; return r; 22 | }; 23 | 24 | void list_free(pListNode list, ListIterator destructor) 25 | { 26 | while(list) { 27 | pListNode n = list->next; 28 | if(destructor) (*destructor)(list, NULL); 29 | free(list); list = n; 30 | }; 31 | }; 32 | 33 | int list_indexof(pListNode list, ListIterator test, void *param) 34 | { 35 | int r; 36 | if(!list) return -1; 37 | if((*test)(list, param)) return 0; 38 | r = list_indexof(list->next, test, param); 39 | return (r==-1)?-1:r+1; 40 | }; 41 | 42 | int list_length(pListNode list) 43 | { 44 | return((list)?list_length(list->next)+1:0); 45 | }; 46 | 47 | void list_mapcar(pListNode list, ListIterator iter, void *param) 48 | { 49 | while(list) { 50 | (*iter)(list->data, param); 51 | list=list->next; 52 | }; 53 | }; 54 | 55 | pListNode list_nth(pListNode list, int index) 56 | { 57 | return(list?(index?list_nth(list->next, index-1):list):NULL); 58 | }; 59 | 60 | int free_car_destructor(pListNode n, void *foo) 61 | { 62 | free(n->data); 63 | }; 64 | -------------------------------------------------------------------------------- /src/ptrlist.h: -------------------------------------------------------------------------------- 1 | /* ptrlist.h acb 28-9-1994 2 | * A package for implementing a generic linked list whose car is a void * 3 | */ 4 | 5 | #ifndef __PTRLIST_H 6 | #define __PTRLIST_H 7 | 8 | typedef struct tagListNode { 9 | void *data; 10 | struct tagListNode *next; 11 | } ListNode, *pListNode; 12 | 13 | /* it is assumed that sizeof(void *) >= sizeof(int) . If this is not the 14 | case, then your system is incredibly bogus. */ 15 | 16 | typedef int (*ListIterator)(pListNode, void *); 17 | 18 | /* 19 | * function prototypes 20 | */ 21 | 22 | pListNode list_append(pListNode a, pListNode b); 23 | 24 | pListNode list_cons(void *car, pListNode cdr); 25 | 26 | /* free each node of the list, first applying destructor to it if nonzero */ 27 | 28 | void list_free(pListNode list, ListIterator destructor); 29 | 30 | /* list_indexof() applies an iterator to each node and returns the index 31 | * of the first node for which the iterator returns a nonzero value */ 32 | 33 | int list_indexof(pListNode list, ListIterator test, void *param); 34 | 35 | int list_length(pListNode list); 36 | 37 | void list_mapcar(pListNode list, ListIterator iter, void *param); 38 | 39 | pListNode list_nth(pListNode list, int index); 40 | 41 | /* a stock destructor which free()s the data of a node */ 42 | 43 | int free_car_destructor(pListNode n, void *foo); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/resolve.c: -------------------------------------------------------------------------------- 1 | /* resolve.c acb 10-9-1994 2 | * routines for recursively resolving a RTN. 3 | */ 4 | 5 | #include 6 | #include 7 | #include 8 | #include "rtn.h" 9 | #include "resolve.h" 10 | #include "dstring.h" 11 | #include "map.h" 12 | #include "transform.h" 13 | #include "variables.h" 14 | #include "machine.h" 15 | 16 | #ifndef __GNUC__ 17 | #define inline /* no inline functions available */ 18 | #endif 19 | 20 | #define MAX(foo,bar) (((foo)>(bar))?(foo):(bar)) 21 | #define MIN(foo,bar) (((foo)<(bar))?(foo):(bar)) 22 | 23 | /* probability frobnostication factor; the higher this is, the more the odds 24 | * are shifted against recent choices */ 25 | 26 | #define FROB_FACTOR 64 27 | 28 | struct _resolve_iter_params { 29 | pRule rules; 30 | char **result; 31 | pParam formal; /* the rule's formal parameters, as defined */ 32 | pParam cooked; /* cooked */ 33 | }; 34 | 35 | extern int trace, old_probability; 36 | extern pListNode transformations; 37 | 38 | static char *_resolve_rule(pRule, pRule, pNode, pListNode, pListNode, 39 | enum resmode); 40 | 41 | static inline char *resolve_option(pRule rules, pOption option, 42 | pParam formal, pParam cooked); 43 | 44 | 45 | /* resolve an atom */ 46 | static inline char *resolve_atom(pNode atom, pRule rules, pListNode formal, pListNode cooked) 47 | { 48 | int index; 49 | char *result=NULL; /* for star and plus */ 50 | int i; 51 | 52 | if(trace) printf("Resolving atom: type = %d, data = \"%s\"\n", 53 | atom->type, atom->data); 54 | switch(atom->type) { 55 | case literal: 56 | return strdup(atom->data); 57 | case symbol: 58 | /* first, check if this symbol is a parameter of the current rule */ 59 | if((index=param_indexof(formal, atom->data))!=-1) { 60 | if(index>=list_length(cooked)) 61 | return(strdup("(parameter off end of list)")); 62 | else 63 | return(strdup(list_nth(cooked, index)->data)); 64 | }; 65 | /* it is not a parameter substitution; resolve from rules */ 66 | return _resolve_rule(rules, rule_find(rules, atom->data), atom->params, 67 | formal, cooked, atom->mode); 68 | case mapping: 69 | if(map_lookup(mappings, atom->data)) 70 | return apply_mapping(resolve_atom(atom->params, rules, formal, 71 | cooked), 72 | map_lookup(mappings, atom->data)); 73 | return apply_xform(resolve_atom(atom->params, rules, formal, cooked), 74 | trans_lookup(transformations, atom->data)); 75 | case deref: 76 | return _resolve_rule(rules, 77 | rule_find(rules, resolve_atom(atom->params, rules, 78 | formal, cooked)), 79 | NULL, formal, cooked, atom->mode); 80 | case var_conddef: { 81 | char *val = var_fetch(atom->data); 82 | if(!val) { 83 | val = resolve_atom(atom->params, rules, formal, cooked); 84 | var_put(atom->data, val); 85 | }; 86 | val = strdup(val); /* make a disposable copy of it */ 87 | return val; 88 | }; 89 | case var_def: { 90 | char *val = resolve_atom(atom->params, rules, formal, cooked); 91 | if(!val) val = "undefined"; 92 | var_put(atom->data, val); 93 | val = strdup(val); /* make a disposable copy of it */ 94 | return val; 95 | }; 96 | case var_ref: { 97 | char *val = var_fetch(atom->data); 98 | if(!val) { 99 | fprintf(stderr, "undefined variable `%s'.\n", atom->data); 100 | exit(1); 101 | }; 102 | return strdup(val); /* make a disposable copy of it */ 103 | }; 104 | case silence: { 105 | free(resolve_atom(atom->params, rules, formal, cooked)); 106 | return NULL; 107 | }; 108 | case code: return exec_stream((pInstr)atom->data); 109 | case plus: 110 | result = resolve_atom(atom->params, rules, formal, cooked); 111 | case star: 112 | while((rand()%5)>1) 113 | result = dstrcat(result, 114 | resolve_atom(atom->params, rules, formal, cooked)); 115 | return result; 116 | case repeat_const: 117 | for(i=0; iint_param; i++) 118 | result = dstrcat(result, 119 | resolve_atom(atom->params, rules, formal, cooked)); 120 | return result; 121 | case repeat_var: { 122 | char *val = var_fetch(atom->data); 123 | if(!val) { 124 | fprintf(stderr, "undefined variable `%s'.\n", atom->data); 125 | exit(1); 126 | }; 127 | for(i=atoi(val); i>0; i--) 128 | result = dstrcat(result, 129 | resolve_atom(atom->params, rules, formal, cooked)); 130 | return result; 131 | }; 132 | case choice: { 133 | int choice; 134 | pOption options=(pOption)atom->data; 135 | int num_options = option_length(options); 136 | 137 | if (trace) printf("last choice: %i\n", atom->last_choice); 138 | do { 139 | choice = random()%num_options; 140 | } while ((choice==atom->last_choice) && (num_options>1)); 141 | if(trace) printf("inline choice: choose %i/%i\n", choice, num_options); 142 | atom->last_choice = choice; 143 | return resolve_option(rules, option_nth(options, choice), 144 | formal, cooked); 145 | }; 146 | 147 | }; 148 | }; 149 | 150 | static void resolve_iterator(pNode atom, struct _resolve_iter_params *prms) 151 | { 152 | *(prms->result) = dstrcat(*(prms->result), 153 | resolve_atom(atom, prms->rules, 154 | prms->formal, prms->cooked)); 155 | }; 156 | 157 | static inline char *resolve_option(pRule rules, pOption option, 158 | pParam formal, pParam cooked) 159 | { 160 | struct _resolve_iter_params prms; 161 | char *result=NULL; 162 | prms.rules = rules; 163 | prms.result = &result; 164 | prms.formal = formal; 165 | prms.cooked = cooked; 166 | node_map(option->atoms, (NodeIterator)&resolve_iterator, (aux_t)&prms); 167 | return result; 168 | }; 169 | 170 | /* resolve a parameter (node) list into a list of strings; now checks a 171 | list of parameters from the parent. */ 172 | 173 | static pListNode resolve_params(pNode in, pRule rules, 174 | pListNode formal, pListNode cooked) 175 | { 176 | int index; 177 | 178 | if(in==(pNode)NULL) return (pParam)NULL; 179 | /* check if it's a cascading parameter */ 180 | if((index=param_indexof(formal, in->data))!=-1) { 181 | char *this_result; 182 | if(trace) { 183 | fprintf(stderr, "resolve_params: formal: "); param_dump(formal); 184 | fprintf(stderr, "\nresolve_params: cooked: "); param_dump(cooked); 185 | fprintf(stderr, "\nin->data: %s\n", in->data); 186 | fprintf(stderr, "index of %s == %i\n", in->data, index); 187 | }; 188 | this_result = (index>=list_length(cooked))?"(parameter off end of list)" 189 | :list_nth(cooked, index)->data; 190 | if(trace) fprintf(stderr, "resolving cascading parameter: %s -> %s\n", 191 | in->data, this_result); 192 | return list_cons(strdup(this_result), 193 | resolve_params(in->next, rules, formal, cooked)); 194 | }; 195 | return list_cons((void *)resolve_atom(in, rules, 196 | rule_find(rules, in->data)? 197 | rule_find(rules, in->data)->params: 198 | NULL, 199 | resolve_params(in->params, rules, 200 | formal, cooked)), 201 | resolve_params(in->next, rules, formal, cooked)); 202 | }; 203 | 204 | /* select an option at random */ 205 | 206 | static int _sum_option_weights(pOption o, int* s) 207 | { 208 | if(trace) fprintf(stderr, "option weight == %i\n", o->randweight); 209 | (*s) += o->randweight; 210 | }; 211 | 212 | static int _incr_option_weight(pOption o, void* foo) 213 | { 214 | #if 0 215 | o->randweight+=FROB_FACTOR; 216 | #else 217 | o->randweight=((o->randweight+1)*3)/2; 218 | #endif 219 | } 220 | 221 | pOption select_option(pOption options, int *last, enum resmode mode) 222 | { 223 | int num_options = option_length(options); 224 | if((old_probability) && (mode==plain)) { 225 | int choice; 226 | /* do it the old way */ 227 | do { 228 | choice=random()%num_options; 229 | } while ((choice==*last) && (num_options>1)); 230 | *last=choice; 231 | return option_nth(options, choice); 232 | } else { 233 | /* do it the new way */ 234 | pOption o=options; 235 | int sum=0; 236 | int ch; 237 | option_map(options, (OptionIterator)_sum_option_weights, (void *)&sum); 238 | if(trace) fprintf(stderr, "total of option weights: %i\n", sum); 239 | ch=sum?random()%sum:0; 240 | if(trace) fprintf(stderr, "random value: %i\n", ch); 241 | while(ch>o->randweight) { 242 | ch -= o->randweight; 243 | o=o->next?o->next:0; 244 | }; 245 | #if 0 246 | o->randweight= MAX(-FROB_FACTOR,o->randweight-((num_options+1)*FROB_FACTOR)); /* make this one less probable */ 247 | #else 248 | o->randweight = 1; 249 | #endif 250 | /* if(o->randweight<0) o->randweight=0;*/ 251 | option_map(options, _incr_option_weight, NULL); 252 | return o; 253 | }; 254 | }; 255 | 256 | /* resolve the rule rule recursively, using rules as the rule-base. 257 | This function now accepts the parent's formal and actual rules 258 | and also the resolution mode. */ 259 | 260 | static char *_resolve_rule(pRule rules, pRule rule, pNode param, 261 | pListNode parent_formal, pListNode parent_cooked, 262 | enum resmode mode) 263 | { 264 | if(rule) { 265 | char *r; 266 | pParam cooked = resolve_params(param, rules, parent_formal, parent_cooked); 267 | int num_options = option_length(rule->options); 268 | int choice; 269 | 270 | if(trace) printf("Resolving rule <%s>\n", rule->symbol); 271 | 272 | /* make the choice */ 273 | 274 | r = resolve_option(rules, 275 | select_option(rule->options, &(rule->last_choice), 276 | mode), rule->params, cooked); 277 | 278 | list_free(cooked, free_car_destructor); 279 | if(trace) printf("resolve_option returned \"%s\"\n", r); 280 | return r; 281 | } else return NULL; 282 | }; 283 | 284 | char *resolve_rule(pRule rules, pRule rule) 285 | { 286 | return _resolve_rule(rules, rule, NULL, NULL, NULL, plain); 287 | }; 288 | 289 | 290 | 291 | 292 | -------------------------------------------------------------------------------- /src/resolve.h: -------------------------------------------------------------------------------- 1 | /* resolve.h acb 10-9-1994 */ 2 | 3 | #ifndef __RESOLVE_H 4 | #define __RESOLVE_H 5 | 6 | char *resolve_rule(pRule rules, pRule rule); 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/resstack.c: -------------------------------------------------------------------------------- 1 | /* resstack.c acb 17-7-1995 2 | * A stack for implementing unique/enumerated rule resolution 3 | */ 4 | 5 | #include 6 | #include "limits.h" 7 | #include "dict.h" 8 | #include "ptrlist.h" 9 | 10 | typedef char res_history[MAX_OPTIONS>>3]; 11 | 12 | #ifndef __GNUC__ 13 | #define inline /* */ 14 | #endif 15 | 16 | static inline void hist_clear(res_history r) { memset(r, 0, MAX_OPTIONS>>3); }; 17 | 18 | static inline int hist_test(res_history r, int bitpos) 19 | { 20 | return (r[bitpos>>3]&(0x01<<(bitpos&7))); 21 | }; 22 | 23 | static inline void hist_set(res_history r, int bitpos) 24 | { 25 | r[bitpos>>3] |= (0x01<<(bitpos&7)); 26 | }; 27 | 28 | struct hist_item { int num_opts; res_history hist; }; 29 | 30 | /* the stack; each stack frame is a list node, whose car is a dictionary 31 | * of hist_item structures. (The car itself is a dictionary, not a pointer to 32 | * one.) */ 33 | 34 | pListNode res_stack=NULL; 35 | 36 | /* push a new stack frame */ 37 | 38 | void resstack_push_new() 39 | { 40 | res_stack = list_cons(NULL, res_stack); 41 | }; 42 | 43 | void resstack_pop() 44 | { 45 | if(res_stack) { 46 | pListNode n; 47 | dict_free(res_stack->data); 48 | n=res_stack->next; 49 | free(res_stack); 50 | res_stack=n; 51 | }; 52 | }; 53 | -------------------------------------------------------------------------------- /src/resstack.h: -------------------------------------------------------------------------------- 1 | /* resstack.h 2 | * Author: Andrew C. Bulhak 3 | * Commenced: Mon Jul 17 02:18:11 1995 4 | */ 5 | 6 | #ifndef __RESSTACK_H 7 | #define __RESSTACK_H 8 | 9 | void resstack_push_new(); 10 | 11 | void resstack_pop(); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /src/rtn.c: -------------------------------------------------------------------------------- 1 | /* rtn.c acb 8-9-1994 */ 2 | 3 | #include 4 | #include "rtn.h" 5 | #include "strfunc.h" 6 | 7 | pNode node_cons(enum nodetype t, char *d, pNode cdr) 8 | { 9 | pNode r; 10 | if(r = (pNode)malloc(sizeof(Node))) { 11 | r->type = t; 12 | r->data = d; /* pre-duplicated in the lexer */ 13 | r->params = NULL; /* parameters, if any, are added later. */ 14 | r->next = cdr; 15 | }; 16 | return r; 17 | }; 18 | 19 | pNode node_append(pNode a, pNode b) 20 | { 21 | pNode r = a; 22 | while(r->next) 23 | r = r->next; 24 | r->next = b; 25 | return a; 26 | }; 27 | 28 | void node_map(pNode list, NodeIterator iter, aux_t param) 29 | { 30 | if(list) { 31 | (*iter)(list, param); 32 | node_map(list->next, iter, param); 33 | }; 34 | }; 35 | 36 | pOption option_cons(pNode car, pOption cdr) 37 | { 38 | pOption r; 39 | if(r=(pOption)malloc(sizeof(Option))) { 40 | r->atoms = car; 41 | r->next = cdr; 42 | r->randweight=4; 43 | }; 44 | return r; 45 | }; 46 | 47 | pOption option_append(pOption a, pOption b) 48 | { 49 | pOption r = a; 50 | while(r->next) 51 | r = r->next; 52 | r->next = b; 53 | return a; 54 | }; 55 | 56 | void option_map(pOption list, OptionIterator iter, aux_t param) 57 | { 58 | if(list) { 59 | (*iter)(list, param); 60 | option_map(list->next, iter, param); 61 | }; 62 | }; 63 | 64 | int option_length(pOption list) 65 | { 66 | return (list)?option_length(list->next)+1:0; 67 | }; 68 | 69 | pOption option_nth(pOption list, int index) 70 | { 71 | return ((list)?((index==0)?list:option_nth(list->next, index-1)):NULL); 72 | }; 73 | 74 | #if 0 75 | pParam param_cons(char *car, pParam cdr) 76 | { 77 | pParam r; 78 | if(r=(pParam)malloc(sizeof(Param))) { 79 | r->name = car; 80 | r->next = cdr; 81 | }; 82 | return r; 83 | }; 84 | 85 | pParam param_append(pParam a, pParam b) 86 | { 87 | pParam r = a; 88 | while(r->next) 89 | r = r->next; 90 | r->next = b; 91 | return a; 92 | }; 93 | 94 | void param_free(pParam list) 95 | { 96 | if(list) { 97 | param_free(list->next); 98 | free(list); 99 | }; 100 | }; 101 | 102 | #endif 103 | 104 | /* return the index of a string in a parameter list, -1 if not present */ 105 | 106 | #if 0 107 | static int _param_indexof(pParam list, char *nm, int futplex) 108 | { 109 | if(!list) return -1; 110 | if(strcmp(nm, list->name)==0) return futplex; 111 | else return _param_indexof(list->next, nm, futplex+1); 112 | }; 113 | #endif 114 | 115 | static int param_indexof_iter(pListNode l, char *str) 116 | { 117 | return(strcmp(l->data, str)==0); 118 | }; 119 | 120 | int param_indexof(pListNode list, char *nm) 121 | { 122 | return list_indexof(list, (ListIterator)¶m_indexof_iter, (void *)nm); 123 | }; 124 | 125 | /* this uses stderr, instead of stdout (as dump_params did). */ 126 | void param_dump(pParam params) 127 | { 128 | if(params) { 129 | fprintf(stderr, "%s ", params->data); 130 | dump_params(params->next); 131 | }; 132 | }; 133 | 134 | /* make a new rule, sans subtrees */ 135 | pRule rule_new(char *symbol, pOption options, pParam params) 136 | { 137 | pRule r; 138 | if(r=(pRule)malloc(sizeof(Rule))) { 139 | r->symbol = symbol; 140 | r->options = options; 141 | r->params = params; 142 | r->left = r->right = (pRule)NULL; 143 | r->last_choice = -1; /* no choices made, so everything's Allowed. */ 144 | }; 145 | return r; 146 | }; 147 | 148 | /* a recursive insertion function */ 149 | 150 | pRule rule_insert(pRule parent, pRule newrule) 151 | { 152 | if(parent) { 153 | if(strcmp(newrule->symbol, parent->symbol)>0) { 154 | parent->right = rule_insert(parent->right, newrule); 155 | return parent; 156 | } else { 157 | parent->left = rule_insert(parent->left, newrule); 158 | return parent; 159 | }; 160 | } else return newrule; 161 | }; 162 | 163 | pRule rule_find(pRule tree, char *name) 164 | { 165 | int c; 166 | if(!tree) return NULL; 167 | c = strcmp(name, tree->symbol); 168 | if(c==0) return tree; 169 | if(c<0) return rule_find(tree->left, name); 170 | return rule_find(tree->right, name); 171 | }; 172 | 173 | void rule_inorder_traverse(pRule tree, RuleIterator iter, aux_t param) 174 | { 175 | if(tree) { 176 | rule_inorder_traverse(tree->left, iter, param); 177 | (*iter)(tree, param); 178 | rule_inorder_traverse(tree->right, iter, param); 179 | }; 180 | }; 181 | -------------------------------------------------------------------------------- /src/rtn.h: -------------------------------------------------------------------------------- 1 | /* rtn.h acb 8-9-1994 2 | * 3 | * Major modifications: 4 | * 17-9-1994: started adding parametrised rules 5 | * 23-9-1994 (?): started adding regular expression-based mappings 6 | * 2[56]-9-1994: started adding dereferencing 7 | * 15-2-1995: Started adding embedded imperative code 8 | * 29-4-1995: Started adding option prespecification and inline choices 9 | * 13-5-1995: Started adding the Kleene star and + operators 10 | * 7-6-1995: Started adding the new random weighting system; this will 11 | * counteract seriality (the tendency for choices of the same 12 | * group to be selected in sequence) more effectively than the 13 | * old "last choice" mechanism. 14 | * 4-7-1995: Started adding the "repeat" operator. 15 | */ 16 | 17 | #ifndef __RTN_H 18 | #define __RTN_H 19 | 20 | #include 21 | 22 | #include "ptrlist.h" 23 | 24 | enum nodetype { 25 | literal, 26 | symbol, 27 | mapping, 28 | deref, 29 | var_conddef, /* conditional variable definition; define if not already 30 | so */ 31 | var_def, /* force definition of a variable */ 32 | var_ref, /* reference a variable */ 33 | code, /* a chunk of code which is executed */ 34 | silence, /* something which silences another node. */ 35 | choice, /* an inline choice */ 36 | star, /* the Kleene star; do something zero or more times */ 37 | plus, /* do something one or more times */ 38 | repeat_const, /* do something a predefined number of times */ 39 | repeat_var /* look up a number of times in a variable */ 40 | }; 41 | 42 | enum resmode { 43 | plain, /* resolve as always, selecting at random */ 44 | unique, /* do not allow duplicate choices until all choices are 45 | exhausted */ 46 | enumerate, /* enumerate all choices on this level */ 47 | pick /* pick n choices without replacement */ 48 | }; 49 | 50 | #define SELECT_RANDOM -1 /* randomly perform the selection process */ 51 | 52 | typedef struct tagNode { 53 | enum nodetype type; 54 | char *data; /* literal text, symbol invocation, mapping invocation, 55 | block of code, name of variable to set or retrieve 56 | or inline option list */ 57 | struct tagNode *params; /* actual parameters, to be evaluated, or subnode 58 | for mapping or conditional definition */ 59 | int int_param; /* an integer argument, such as a constant repeat count */ 60 | int select; 61 | int last_choice; /* for inline choices */ 62 | enum resmode mode; /* mode of resolution */ 63 | int pick_num; /* number to pick */ 64 | struct tagNode *next; 65 | } Node, *pNode; 66 | 67 | typedef struct tagOption { 68 | pNode atoms; 69 | int randweight; /* for the new, improved anti-seriality mechanism */ 70 | struct tagOption *next; 71 | } Option, *pOption; 72 | 73 | /* parameters for parametrised rules */ 74 | 75 | typedef ListNode Param, *pParam; 76 | 77 | /* rules are arranged in a binary tree */ 78 | 79 | typedef struct tagRule { 80 | char *symbol; 81 | pOption options; 82 | pParam params; /* parameters for this rule, or NULL if none are used, */ 83 | struct tagRule *left, *right; 84 | /* added on 07/01/25 AU; a sort of limited memory to counteract seriality 85 | somewhat */ 86 | int last_choice; /* for the old anti-seriality mechanism */ 87 | } Rule, *pRule; 88 | 89 | typedef void *aux_t; /* for auxilliary arguments to iterators */ 90 | 91 | typedef int (*NodeIterator)(pNode, aux_t); 92 | 93 | typedef int (*OptionIterator)(pOption, aux_t); 94 | 95 | typedef ListIterator ParamIterator; 96 | 97 | typedef int (*RuleIterator)(pRule, aux_t); 98 | 99 | /* 100 | * function prototypes 101 | */ 102 | 103 | pNode node_cons(enum nodetype t, char *d, pNode cdr); 104 | 105 | pNode node_append(pNode a, pNode b); 106 | 107 | void node_map(pNode list, NodeIterator iter, aux_t param); 108 | 109 | pOption option_cons(pNode car, pOption cdr); 110 | 111 | pOption option_append(pOption a, pOption b); 112 | 113 | int option_length(pOption list); 114 | 115 | pOption option_nth(pOption list, int index); 116 | 117 | void option_map(pOption list, OptionIterator iter, aux_t param); 118 | 119 | int param_indexof(pListNode list, char *nm); 120 | 121 | /* make a new rule, sans subtrees */ 122 | pRule rule_new(char *symbol, pOption options, pParam params); 123 | 124 | /* a recursive insertion function */ 125 | 126 | pRule rule_insert(pRule parent, pRule newrule); 127 | 128 | /* find a rule */ 129 | 130 | pRule rule_find(pRule tree, char *name); 131 | 132 | /* traverse the rule tree in infix order */ 133 | 134 | void rule_inorder_traverse(pRule tree, RuleIterator iter, aux_t param); 135 | 136 | #endif 137 | -------------------------------------------------------------------------------- /src/strfunc.c: -------------------------------------------------------------------------------- 1 | /* strfunc.c acb 12-6-1994 2 | * string-handling utility functions for pb, taken from rml 3 | */ 4 | 5 | #include 6 | #include 7 | #include "strfunc.h" 8 | 9 | #ifndef min 10 | #define min(x,y) (((x)<(y))?(x):(y)) 11 | #endif 12 | 13 | /* allocate a new string containing the first l characters of s */ 14 | 15 | char *strnnew(char *s, int l) 16 | { 17 | int actl; /* actual length */ 18 | char *result; 19 | if(!s) return NULL; 20 | actl = min(strlen(s), l); 21 | result = (char *) malloc(actl+1); 22 | strncpy(result, s, actl); 23 | result[actl]=0; 24 | return result; 25 | }; 26 | 27 | #ifndef HAVE_STRDUP 28 | char *strdup(char *s) { return strnnew(s, strlen(s)); } 29 | #endif 30 | 31 | /* concat() allocates a new string and strcat()s two strings together into it. 32 | */ 33 | 34 | char *concat(char *foo, char *bar) 35 | { 36 | char *r; 37 | if(!foo && !bar) return NULL; 38 | if(!foo) return strnnew(bar, strlen(bar)); 39 | if(!bar) return strnnew(foo, strlen(foo)); 40 | r = (char *) malloc(strlen(foo)+strlen(bar)+1); 41 | if(r) { 42 | strcpy(r, foo); 43 | strcat(r, bar); 44 | r[strlen(foo)+strlen(bar)] = '\0'; 45 | }; 46 | return r; 47 | }; 48 | 49 | /* cookstr() goes through the supplied string, converting escape sequences 50 | to the characters that they represent. Since this never increases the 51 | length of the string, it is safe to do in situ. */ 52 | 53 | int cookstr(char *str) 54 | { 55 | char *from=str, *to=str; 56 | while(*from) { 57 | if((*from)=='\\') { 58 | from++; 59 | if(*from) { 60 | switch(*from) { 61 | case 'n': *(to++) = '\n'; break; 62 | case 't': *(to++) = '\t'; break; 63 | case 'v': *(to++) = '\v'; break; 64 | case 'b': *(to++) = '\b'; break; 65 | case 'r': *(to++) = '\r'; break; 66 | case 'f': *(to++) = '\f'; break; 67 | case 'a': *(to++) = '\a'; break; 68 | default: *(to++)=*(from); 69 | }; 70 | from++; 71 | }; 72 | } else { 73 | *(to++)=*(from++); 74 | }; 75 | }; 76 | *to='\0'; 77 | return to-from; 78 | }; 79 | 80 | /* itoa() formats an integer into a string, allocated on the heap */ 81 | 82 | char *itoa(int i) 83 | { char buffer[16]; sprintf(buffer, "%i", i); return strdup(buffer); }; 84 | -------------------------------------------------------------------------------- /src/strfunc.h: -------------------------------------------------------------------------------- 1 | /* strfunc.h acb 12-6-1994 2 | * string-handling utility functions for rtpp 3 | */ 4 | 5 | #ifndef __STRFUNC_H 6 | #define __STRFUNC_H 7 | 8 | #include "config.h" 9 | 10 | /* kludge to patch a gaping hole in the Ultrix libc */ 11 | 12 | #ifndef HAVE_STRDUP 13 | char *strdup(char *); 14 | #endif 15 | 16 | /* allocate a new string containing the first l characters of s */ 17 | 18 | char *strnnew(char *s, int l); 19 | 20 | /* concat() allocates a new string and strcat()s two strings together into it. 21 | */ 22 | 23 | char *concat(char *foo, char *bar); 24 | 25 | /* cookstr() goes through the supplied string, converting escape sequences 26 | to the characters that they represent. Since this never increases the 27 | length of the string, it is safe to do in situ. */ 28 | 29 | int cookstr(char *str); 30 | 31 | /* itoa() formats an integer into a string, allocated on the heap */ 32 | 33 | char *itoa(int i); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/transform.c: -------------------------------------------------------------------------------- 1 | /* transform.c acb 9-2-1995 2 | * sed-style transformation support for pb 3 | */ 4 | 5 | #include 6 | #include "transform.h" 7 | 8 | /* regex_subst() does not deallocate its input -- its caller has to do this */ 9 | char *regex_subst(char *in, char *from, char *to); /* in map.c */ 10 | 11 | pTransformation trans_lookup(pListNode list, char *name) 12 | { 13 | return (pTransformation)((list)?( 14 | (strcmp(((pTransformation)list->data)->name, name)==0)?list->data: 15 | trans_lookup(list->next, name)):NULL); 16 | }; 17 | 18 | 19 | /* match an option to a string, using regular expressions (ooh!) */ 20 | pTransOpt transopt_match(pListNode list, char *string) 21 | { 22 | while(list) { 23 | regex_t key_regex; 24 | regmatch_t match; 25 | pTransOpt opt=(pTransOpt)list->data; 26 | 27 | regcomp(&key_regex, opt->key, 0); 28 | 29 | if(regexec(&key_regex, string, 1, &match, 0)==0) { 30 | regfree(&key_regex); 31 | return opt; 32 | }; 33 | 34 | regfree(&key_regex); 35 | list=list->next; 36 | }; 37 | return NULL; 38 | }; 39 | 40 | /* put an address integer into normal form */ 41 | static inline int addr_normalise(int addr, char *input) 42 | { 43 | int l=strlen(input); 44 | if(l==0) return 0; 45 | while(addr<0) addr+=l; 46 | addr %= l; 47 | return addr; 48 | }; 49 | 50 | /* apply_xform_cmd() either returns or frees its input */ 51 | 52 | static char *apply_xform_cmd(char *input, pTransCmd cmd) 53 | { 54 | int from, to, len, i; 55 | char *r; 56 | 57 | if(cmd->addr) { 58 | from = addr_normalise(*(cmd->addr), input); 59 | to = addr_normalise(*(cmd->addr+1), input); 60 | } else { from = 0; to = strlen(input)-1; }; 61 | len = to-from+1; 62 | 63 | switch(cmd->cmdname[0]) { 64 | case 'd': 65 | r=malloc(strlen(input)-len); *r = '\0'; 66 | strncpy(r, input, from); strncat(r, input+to+1, strlen(input)-(to+1)); 67 | free(input); return r; 68 | case 'l': /* lowercase the range */ 69 | for(i=from; i<=to; i++) 70 | input[i]=tolower(input[i]); 71 | return input; 72 | case 's': /* FIXME: add some sort of argument count checking */ 73 | r = regex_subst(input, list_nth(cmd->params, 0)->data, 74 | list_nth(cmd->params, 1)->data); 75 | free(input); 76 | return r; 77 | case 'u': /* uppercase the range */ 78 | for(i=from; i<=to; i++) 79 | input[i]=toupper(input[i]); 80 | return input; 81 | }; 82 | fprintf(stderr, "Warning: ignoring undefined transformation `%s'\n", 83 | cmd->cmdname); 84 | return input; 85 | }; 86 | 87 | /* apply_xform() either returns or frees its input */ 88 | 89 | char *apply_xform(char *input, pTransformation xfm) 90 | { 91 | pTransOpt option; 92 | pTransCmd cmd; 93 | if(!xfm) return input; 94 | 95 | option = transopt_match(xfm->options, input); 96 | 97 | if(!option) return input; 98 | cmd = option->cmds; 99 | 100 | while(cmd) { 101 | input = apply_xform_cmd(input, cmd); 102 | cmd = cmd->next; 103 | }; 104 | return input; 105 | }; 106 | -------------------------------------------------------------------------------- /src/transform.h: -------------------------------------------------------------------------------- 1 | /* transform.h acb 28-9-1994 2 | * sed-style transformation support for pb 3 | */ 4 | 5 | #ifndef __TRANSFORM_H 6 | #define __TRANSFORM_H 7 | 8 | #include 9 | #include "ptrlist.h" 10 | #include "config.h" 11 | #include /* the POSIX.2 regular expression functions */ 12 | 13 | #ifndef __GNUC__ 14 | #define inline /**/ 15 | #endif 16 | 17 | #define CMDNAMELENGTH 4 18 | 19 | typedef int AddrRange[2]; 20 | 21 | typedef struct tagTransCmd { 22 | int *addr; 23 | char cmdname[CMDNAMELENGTH]; 24 | pListNode params; 25 | struct tagTransCmd *next; 26 | } TransCmd, *pTransCmd; 27 | 28 | /* the following are placed into a list */ 29 | 30 | typedef struct tagTransOpt { 31 | char *key; 32 | pTransCmd cmds; 33 | } TransOpt, *pTransOpt; 34 | 35 | typedef struct tagTransformation { 36 | char *name; 37 | pListNode options; 38 | } Transformation, *pTransformation; 39 | 40 | 41 | extern pListNode transformations; /* in parser.y -- all this to get out of 42 | adding a new source file to Makefile! 43 | Sheesh! */ 44 | 45 | /* even if we don't have inline, we don't lose anything by putting these 46 | * in the header, as only the parser invokes them. 47 | */ 48 | 49 | static inline int *new_addr_range(int a, int b) { 50 | int *r = (int *)malloc(2*sizeof(int)); r[0]=a; r[1]=b; return r; 51 | }; 52 | 53 | static inline pTransCmd new_transcmd(int *addr, char *id, pListNode args) 54 | { 55 | pTransCmd r = (pTransCmd) malloc(sizeof(TransCmd)); r->addr = addr; 56 | strncpy(r->cmdname, id, CMDNAMELENGTH-1); free(id); /* we can do this */ 57 | r->params = args; r->next = NULL; return r; 58 | }; 59 | 60 | static inline pTransOpt new_transopt(char *key, pTransCmd cmds) 61 | { 62 | pTransOpt r = (pTransOpt) malloc(sizeof(TransOpt)); 63 | r->key = key; r->cmds = cmds; return r; 64 | }; 65 | 66 | static inline pTransformation new_transformation(char *name, pListNode opts) 67 | { 68 | pTransformation r = (pTransformation) malloc(sizeof(Transformation)); 69 | r->name = name; r->options = opts; return r; 70 | }; 71 | 72 | pTransformation trans_lookup(pListNode list, char *name); 73 | 74 | 75 | /* match an option to a string, using regular expressions (ooh!) */ 76 | pTransOpt transopt_match(pListNode list, char *string); 77 | 78 | 79 | /* apply_xform() either returns or frees its input */ 80 | char *apply_xform(char *input, pTransformation xfm); 81 | 82 | #endif 83 | -------------------------------------------------------------------------------- /src/variables.c: -------------------------------------------------------------------------------- 1 | /* variables.c acb Mungday 3161 (5-1-1995) 2 | * global, contextual variables. 3 | */ 4 | 5 | #include 6 | #include 7 | #include "variables.h" 8 | 9 | #ifndef __GNUC__ 10 | #define inline /* */ 11 | #endif 12 | 13 | /* variables are stored in a tree */ 14 | 15 | struct var *vars = NULL; 16 | 17 | static inline struct var *new_str_var(char *name, char *val) { 18 | struct var *v = (struct var *)malloc(sizeof(struct var)); 19 | v->name = name; v->type = string_t; v->value.s = val; 20 | v->left = v->right = NULL; 21 | }; 22 | 23 | static inline struct var *new_int_var(char *name, int val) { 24 | struct var *v = (struct var *)malloc(sizeof(struct var)); 25 | v->name = name; v->type = int_t; v->value.i = val; 26 | v->left = v->right = NULL; 27 | }; 28 | 29 | static struct var *var_insert_str(struct var *tree, char *name, char *val) 30 | { 31 | if(tree) { 32 | if(strcmp(name, tree->name)==0) { 33 | tree->type = string_t; 34 | tree->value.s = val; 35 | } 36 | else 37 | if(strcmp(name, tree->name)<0) 38 | tree->left = var_insert_str(tree->left, name, val); 39 | else 40 | tree->right = var_insert_str(tree->right, name, val); 41 | } else { 42 | tree = new_str_var(name, val); 43 | }; 44 | return tree; 45 | }; 46 | 47 | static struct var *var_insert_int(struct var *tree, char *name, int val) 48 | { 49 | if(tree) { 50 | if(strcmp(name, tree->name)==0) { 51 | tree->type = int_t; 52 | tree->value.i = val; 53 | } else 54 | if(strcmp(name, tree->name)<0) 55 | tree->left = var_insert_int(tree->left, name, val); 56 | else 57 | tree->right = var_insert_int(tree->right, name, val); 58 | } else { 59 | tree = new_int_var(name, val); 60 | }; 61 | return tree; 62 | }; 63 | 64 | inline struct var *var_lookup(struct var *tree, char *key) 65 | { 66 | if(!tree) return NULL; 67 | if(strcmp(tree->name, key)==0) return tree; 68 | return var_lookup((strcmp(tree->name, key)>0)?tree->left:tree->right, key); 69 | }; 70 | 71 | type_t var_type(struct var *tree, char *key) 72 | { 73 | struct var *v = var_lookup(tree, key); 74 | return v?v->type:mu; 75 | }; 76 | 77 | /* retrieve a variable's contents, and make a string if need be */ 78 | char *var_fetch(char *var_name) 79 | { 80 | struct var *v = var_lookup(vars, var_name); 81 | if(v) { 82 | char *foo; 83 | switch(v->type) { 84 | case string_t: return v->value.s; 85 | case int_t: foo = (char *)malloc(16); sprintf(foo, "%i", v->value.i); 86 | return foo; 87 | } 88 | }; 89 | return NULL; 90 | }; 91 | 92 | int var_fetch_int(char *var_name) 93 | { 94 | struct var *v = var_lookup(vars, var_name); 95 | if(v) { 96 | switch(v->type) { 97 | case int_t: return v->value.i; 98 | } 99 | }; 100 | return 0; 101 | }; 102 | 103 | void var_put(char *var_name, char *value) 104 | { 105 | vars = var_insert_str(vars, var_name, value); 106 | }; 107 | 108 | void var_put_int(char *var_name, int value) 109 | { 110 | vars = var_insert_int(vars, var_name, value); 111 | }; 112 | 113 | 114 | -------------------------------------------------------------------------------- /src/variables.h: -------------------------------------------------------------------------------- 1 | /* variables.h acb Mungday 3161 (5-1-1995) 2 | * global, contextual variables. 3 | */ 4 | 5 | /* variables are designed to give some semblance of context, i.e., by 6 | * storing a previous choice in a variable for future use. These are 7 | * the sorts of operations which are anticipated: 8 | 9 | 10 | foo: var< 6 | #include 7 | 8 | #ifndef MIN 9 | #define MIN(a,b) ((aspace && !start) { 47 | /* break here */ 48 | putc('\n', f); 49 | start = 1; 50 | space = cols-1; 51 | } 52 | 53 | space -= n+1; 54 | for(i=0; i 2 | 3 | void *xmalloc(int size) 4 | { 5 | return malloc(size); 6 | } 7 | 8 | --------------------------------------------------------------------------------