Mercurial > repo
changeset 4215:7a6bc310b732
<shachaf> tar xjf ploki-0.6.5.1.tar.bz2
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/Compile Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +#!/bin/sh +echo cc -o ploki *.c -lm +cc -o ploki *.c -lm
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/GNUmakefile Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,22 @@ +.PHONY: all clean realclean distclean dist remake + +include MakeSkel + +$(OBJ:.o=.depend): %.depend: %.c %.h + $(DEPEND) $< >$@ + +-include $(OBJ:.o=.depend) + +Makefile: MakeSkel GNUmakefile $(OBJ:.o=.depend) + $(RMF) Makefile + $(CP) MakeSkel Makefile + $(CAT) *.depend >>Makefile + +.PHONY: dist +dist: Makefile tags distclean + plokidir="`$(BASENAME) \"\`$(PWD)\`\"`" \ + version="`$(CAT) VERSION`" && \ + cd .. && \ + $(RMF) "ploki-$$version.tar$(ZIP_EXT)" && \ + $(TAR) -cf "ploki-$$version.tar" --exclude-from="$$plokidir/IGNORE" "$$plokidir" && \ + $(ZIP) "ploki-$$version.tar"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/IGNORE Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +.git
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/IO.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,515 @@ +#include "config.h" +#include "IO.h" +#include "Str.h" +#include "main.h" +#include "main_io.h" +#include "xmalloc.h" +#include "zz.h" + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +struct IO { + struct IO *prev, *next; + enum io_flags mode; + FILE *fp; + char *name; + size_t refs; + String *buf; + long told; + enum { + DI_NONE, + DI_RD, + DI_WR + } dirct; +}; + +static IO *Root; + +static void sanitycheck(enum io_flags m) { + #if !DEBUG_P + (void)m; + #endif + assert( + ( + m & IO_READ || + m & IO_WRITE || + m & IO_APPEND + ) && + !( + m & IO_WRITE && + m & IO_APPEND + ) && + ( + !(m & IO_BUFFERED) || m & IO_READ + ) && + ( + !(m & IO_AUTOFLUSH) || + ( + m & IO_WRITE || + m & IO_APPEND + ) + ) && + ( + !(m & IO_WRITE) || (m & IO_TRUNCATE || m & IO_READ) + ) && + ( + !(m & IO_TRUNCATE) || m & IO_WRITE + ) + ); +} + +void io_init(void) { +} + +static void io_delete(IO *io) { + if (io->mode & IO_BUFFERED) { + St_clear(io->buf); + xfree(io->buf); + } + if (io->fp && io->fp != stderr) { + if (fclose(io->fp)) { + fprintf(io_fp(Err), "%s: %s: %s\n", Prog, io->name, strerror(errno)); + } + } + xfree(io->name); + if (io->prev) { + io->prev->next = io->next; + } else { + assert(io == Root); + Root = io->next; + } + if (io->next) { + io->next->prev = io->prev; + } + xfree(io); +} + +void io_end(void) { + while (Root) { + io_delete(Root); + } +} + +static char *xstrdup(const char *s) { + const size_t len = strlen(s) + 1; + char *const tmp = xmalloc(len, sizeof *tmp); + memcpy(tmp, s, len); + return tmp; +} + +IO *io_enter(const char *name, FILE *fp, enum io_flags mode) { + IO *io; + sanitycheck(mode); + io = xmalloc(1, sizeof *io); + io->fp = fp; + io->mode = mode; + if (mode & IO_BUFFERED) { + io->buf = xmalloc(1, sizeof *io->buf); + St_init(io->buf); + io->told = -1; + } + io->name = xstrdup(name); + io->refs = 1; + + io->dirct = DI_NONE; + + io->prev = NULL; + io->next = Root; + if (Root) { + Root->prev = io; + } + Root = io; + return io; +} + +const char *io_name(const IO *io, String *s) { + if (s) { + St_cpy_s(s, io->name); + } + return io->name; +} + +IO *io_open(const char *name, enum io_flags mode) { + FILE *fp; + char mbuf[4], *p = mbuf; + sanitycheck(mode); + + if (mode & IO_APPEND) { + *p++ = 'a'; + if (mode & IO_READ) { + *p++ = '+'; + } + } else if (mode & IO_WRITE) { + if (mode & IO_TRUNCATE) { + *p++ = 'w'; + if (mode & IO_READ) { + *p++ = '+'; + } + } else { + assert(mode & IO_READ); + *p++ = 'r'; + *p++ = '+'; + } + } else { + assert(mode & IO_READ); + *p++ = 'r'; + } + + if (mode & IO_BINARY) { + *p++ = 'b'; + } + *p = '\0'; + + if (!(fp = fopen(name, mbuf))) { + return NULL; + } + return io_enter(name, fp, mode); +} + +IO *io_incr(IO *io) { + ++io->refs; + return io; +} + +void io_decr(IO *io) { + if (!--io->refs) { + io_delete(io); + } +} + +int io_close(IO *io) { + int ret; + assert(io->fp != NULL); + ret = fclose(io->fp); + io->fp = NULL; + if (io->mode & IO_BUFFERED) { + St_clear(io->buf); + xfree(io->buf); + io->mode &= ~IO_BUFFERED; + } + return ret; +} + +int io_bufred(const IO *io) { + return !!(io->mode & IO_BUFFERED); +} + +void io_unbuffer(IO *io) { + assert(io->mode & IO_BUFFERED); + if (St_len(io->buf) && io->told != -1) { + io_seek(io, io->told, SEEK_SET); + } + St_clear(io->buf); + xfree(io->buf); + io->mode &= ~IO_BUFFERED; +} + +FILE *io_fp(const IO *io) { + return io->fp; +} + +static void bufk(IO *f, size_t n) { + String tmp; + assert(f->mode & IO_BUFFERED); + + if (St_len(f->buf) >= n || feof(f->fp) || ferror(f->fp)) { + return; + } + + assert(f->dirct != DI_WR); + #if 0 + if (f->dirct == DI_WR) { + io_seek(f, 0, SEEK_CUR); + } + f->dirct = DI_RD; + #endif + + if (!(St_len(f->buf) || f->mode & IO_BINARY)) { + f->told = ftell(f->fp); + } + + St_init(&tmp); + while ( + St_len(f->buf) < n && + !feof(f->fp) && !ferror(f->fp) && + St_read(&tmp, f->fp, n - St_len(f->buf)) + ) { + St_cat(f->buf, &tmp); + } + St_clear(&tmp); +} + +#ifdef EBADF + #define BADF ((void)(errno = EBADF)) +#else + #define BADF ((void)0) +#endif + +#define XMODE(c, x) \ +do { \ + if (!(c)) { \ + BADF; \ + return (x); \ + } \ +} while (0) + +#define WMODE(f, x) XMODE((f)->mode & IO_WRITE || (f)->mode & IO_APPEND, (x)) +#define PMODE(f, x) XMODE((f)->mode & IO_BUFFERED, (x)) +#define RMODE(f, x) XMODE((f)->mode & IO_READ, (x)) + +const char *io_bufptr(IO *io) { + PMODE(io, NULL); + return St_ptr(io->buf); +} + +int io_flush(IO *f) { + WMODE(f, EOF); + return fflush(f->fp); +} + +int io_err(const IO *f) { + return ferror(f->fp); +} + +int io_eof(const IO *f) { + return feof(f->fp); +} + +int io_peek(IO *f, size_t pos) { + PMODE(f, EOF); + bufk(f, pos + 1); + if (St_len(f->buf) <= pos) { + return EOF; + } + return ST_INDEX(f->buf, pos); +} + +int io_cmppeek(IO *f, size_t o, const void *p, size_t n) { + size_t i; + PMODE(f, -1); + + for (i = 0; i < n; ++i) { + bufk(f, o + i + 1u); + if (ST_INDEX(f->buf, o + i) != i[(const unsigned char *)p]) { + return 1; + } + } + return 0; +} + +int io_xcmp(IO *f, size_t a, size_t b, size_t n) { + const size_t max = a > b ? a : b; + PMODE(f, -1); + bufk(f, max + n); + if (St_len(f->buf) < max + n) { + return 1; + } + return memcmp(St_ptr(f->buf) + a, St_ptr(f->buf) + b, n) != 0; +} + +size_t io_read(IO *f, String *s, size_t n) { + RMODE(f, -1); + + if (f->mode & IO_BUFFERED) { + String null; + size_t old; + + bufk(f, n); + old = St_len(f->buf); + St_init(&null); + St_substr(s, f->buf, 0, n, &null); + St_clear(&null); + old -= St_len(f->buf); + if (St_len(f->buf) && old && !(f->mode & IO_BINARY) && f->told != -1) { + const long keep = ftell(f->fp); + if (fseek(f->fp, f->told, SEEK_SET) != -1) { + size_t i; + for (i = 0; i < old; ++i) { + getc(f->fp); + } + f->told = ftell(f->fp); + f->dirct = DI_RD; + fseek(f->fp, keep, SEEK_SET); + } + } + return old; + } else { + if (f->dirct == DI_WR) { + fseek(f->fp, 0, SEEK_CUR); + } + f->dirct = DI_RD; + return St_read(s, f->fp, n); + } +} + +int io_getc(IO *f) { + RMODE(f, EOF); + + if (f->mode & IO_BUFFERED) { + int c; + bufk(f, 1); + c = St_shift(f->buf); + if (St_len(f->buf) && c != EOF && !(f->mode & IO_BINARY) && f->told != -1) { + const long keep = ftell(f->fp); + if (fseek(f->fp, f->told, SEEK_SET) != -1) { + getc(f->fp); + f->told = ftell(f->fp); + f->dirct = DI_RD; + fseek(f->fp, keep, SEEK_SET); + } + } + return c; + } + + if (f->dirct == DI_WR) { + fseek(f->fp, 0, SEEK_CUR); + } + f->dirct = DI_RD; + return getc(f->fp); +} + +size_t io_getline(IO *f, String *s) { + RMODE(f, -1); + + if (f->mode & IO_BUFFERED) { + size_t p; + size_t old; + + p = St_chr(f->buf, '\n') + 1u; + if (p) { + old = St_len(f->buf); + if (s) { + St_cpy_m(s, St_ptr(f->buf), p); + } + St_del(f->buf, 0, p); + } else { + for (p = St_len(f->buf); io_peek(f, p) != EOF; ++p) { + if (ST_LASTCHAR(f->buf) == '\n') { + break; + } + } + old = St_len(f->buf); + if (s) { + St_cpy(s, f->buf); + } + St_zero(f->buf); + } + old -= St_len(f->buf); + if (St_len(f->buf) && old && !(f->mode & IO_BINARY) && f->told != -1) { + const long keep = ftell(f->fp); + if (fseek(f->fp, f->told, SEEK_SET) != -1) { + size_t i; + for (i = 0; i < old; ++i) { + getc(f->fp); + } + f->dirct = DI_RD; + f->told = ftell(f->fp); + fseek(f->fp, keep, SEEK_SET); + } + } + return old; + } else { + int c; + size_t n; + + if (f->dirct == DI_WR) { + fseek(f->fp, 0, SEEK_CUR); + } + f->dirct = DI_RD; + + if (s) { + St_zero(s); + } + n = 0; + while ((c = getc(f->fp)) != EOF) { + if (s) { + St_cat_c(s, c); + } + ++n; + if (c == '\n') { + break; + } + } + if (!n && ferror(f->fp)) { + return -1; + } + return n; + } +} + +size_t io_write(IO *f, const String *s) { + size_t ret; + WMODE(f, -1); + if (f->dirct == DI_RD) { + fseek(f->fp, 0, SEEK_CUR); + } + f->dirct = DI_WR; + ret = ST_WRITE(s, f->fp); + if (f->mode & IO_AUTOFLUSH) { + fflush(f->fp); + } + return ret; +} + +size_t io_write_m(IO *f, const void *p, size_t n) { + size_t ret; + WMODE(f, -1); + if (f->dirct == DI_RD) { + fseek(f->fp, 0, SEEK_CUR); + } + f->dirct = DI_WR; + ret = fwrite(p, 1, n, f->fp); + if (f->mode & IO_AUTOFLUSH) { + fflush(f->fp); + } + return ret; +} + +size_t io_write_s(IO *f, const char *s) { + return io_write_m(f, s, strlen(s)); +} + +int io_putc(IO *f, int c) { + int ret; + WMODE(f, EOF); + if (f->dirct == DI_RD) { + fseek(f->fp, 0, SEEK_CUR); + } + f->dirct = DI_WR; + ret = putc(c, f->fp); + if (f->mode & IO_AUTOFLUSH) { + fflush(f->fp); + } + return ret; +} + +long io_tell(IO *f) { + if (f->mode & IO_BUFFERED) { + if (f->mode & IO_BINARY) { + const long ret = ftell(f->fp); + if (ret == -1) { + return ret; + } + return ret - St_len(f->buf); + } + if (St_len(f->buf)) { + return f->told; + } + } + return ftell(f->fp); +} + +int io_seek(IO *f, long off, enum io_whence w) { + if (f->mode & IO_BUFFERED) { + St_zero(f->buf); + } + f->dirct = DI_NONE; + return fseek(f->fp, off, w); +} + +void io_clearerr(IO *f) { + clearerr(f->fp); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/IO.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +IO.o: IO.c config.h IO.h Str.h main.h main_io.h xmalloc.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/IO.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,65 @@ +#ifndef IO_H_ +#define IO_H_ + +#include "config.h" +#include "Str.h" + +#include <stdio.h> + +typedef struct IO IO; + +enum io_flags { + IO_BINARY = 1, + IO_READ = 2 * IO_BINARY, + IO_WRITE = 2 * IO_READ, + IO_APPEND = 2 * IO_WRITE, + IO_TRUNCATE = 2 * IO_APPEND, + IO_BUFFERED = 2 * IO_TRUNCATE, + IO_AUTOFLUSH = 2 * IO_BUFFERED +}; + +enum io_whence { + IOS_START = SEEK_SET, + IOS_CUR = SEEK_CUR, + IOS_END = SEEK_END +}; + +void io_init(void); +void io_end(void); +const char *io_name(const IO *, String *); +IO *io_enter(const char *, FILE *, enum io_flags); +IO *io_open(const char *, enum io_flags); +IO *io_incr(IO *); +void io_decr(IO *); +int io_close(IO *); + +ATTR_PURE +int io_bufred(const IO *); +void io_unbuffer(IO *); +const char *io_bufptr(IO *); + +ATTR_PURE +FILE *io_fp(const IO *); + +int io_flush(IO *); +ATTR_PURE +int io_err(const IO *); +ATTR_PURE +int io_eof(const IO *); +int io_peek(IO *, size_t); +int io_cmppeek(IO *, size_t, const void *, size_t); +int io_xcmp(IO *, size_t, size_t, size_t); + +size_t io_read(IO *, String *, size_t); +int io_getc(IO *); +size_t io_getline(IO *, String *); +size_t io_write(IO *, const String *); +size_t io_write_m(IO *, const void *, size_t); +size_t io_write_s(IO *, const char *); +int io_putc(IO *, int); + +long io_tell(IO *); +int io_seek(IO *, long, enum io_whence); +void io_clearerr(IO *); + +#endif /* IO_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/MakeSkel Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,73 @@ +# vi: set ft=make: +PREFIX = /usr/local +INSTDIR = $(PREFIX)/bin + +CC = gcc +#CC = cc + +#COPT = -DDEBUGGING -g +COPT = -g -O2 +#COPT = -xO4 -xalias_level=std -xbuiltin=%all -xdepend -xinline=%auto -xlibmil -xtarget=native +#COPT = -O +#COPT = + +LDOPT = +#LDOPT = -s + +CPP = $(CC) -E +#CPP = cpp + +DEPEND = $(CPP) -MM +#DEPEND = $(CC) -xM1 + +CFLAGS = $(COPT) -W -Wall -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -std=gnu9x -pedantic -fstrict-aliasing -pipe +#CFLAGS = $(COPT) -W -Wall -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wdisabled-optimization -std=gnu99 -pedantic -fstrict-aliasing -pipe +#CFLAGS = $(COPT) -Xc +#CFLAGS = $(COPT) + +LDFLAGS = $(LDOPT) -lm + +ECHO = echo +CAT = cat +CP = cp +RMF = rm -f +TAR = tar +CTAGS = ctags +#CTAGS = ctags --langmap=c:.c.h +ZIP = bzip2 +ZIP_EXT = .bz2 +BASENAME = basename +PWD = pwd + +# # # # # + +OBJ = IO.o Str.o atechit.o compile.o deparse.o expr.o hang.o hash.o inc.o \ + kork.o list.o main.o mars.o match.o op.o opt.o parse.o pp.o random.o \ + re.o run.o strhash.o strutil.o sub.o text.o transmogrify.o val.o \ + variable.o venus.o version.o xmalloc.o zz.o + +all: tags ploki + +tags: *.c *.h + $(CTAGS) *.c *.h + +distclean: clean + $(RMF) core examples/core a.out +clean: + $(RMF) *.o ploki +realclean: clean + $(RMF) *.depend Makefile + +remake: clean all + +ploki: $(OBJ) + $(CC) -o ploki $(OBJ) $(LDFLAGS) + +install: ploki + $(CP) ploki '$(INSTDIR)/' + +version.c: version.c.in VERSION + $(CP) version.c.in version.c + $(ECHO) '"'"`$(CAT) VERSION`"'";' >>version.c + +########################################################################
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/Makefile Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,135 @@ +# vi: set ft=make: +PREFIX = /usr/local +INSTDIR = $(PREFIX)/bin + +CC = gcc +#CC = cc + +#COPT = -DDEBUGGING -g +COPT = -g -O2 +#COPT = -xO4 -xalias_level=std -xbuiltin=%all -xdepend -xinline=%auto -xlibmil -xtarget=native +#COPT = -O +#COPT = + +LDOPT = +#LDOPT = -s + +CPP = $(CC) -E +#CPP = cpp + +DEPEND = $(CPP) -MM +#DEPEND = $(CC) -xM1 + +CFLAGS = $(COPT) -W -Wall -Wundef -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -std=gnu9x -pedantic -fstrict-aliasing -pipe +#CFLAGS = $(COPT) -W -Wall -Wundef -Wendif-labels -Wshadow -Wpointer-arith -Wcast-align -Wstrict-prototypes -Wmissing-prototypes -Wnested-externs -Winline -Wdisabled-optimization -std=gnu99 -pedantic -fstrict-aliasing -pipe +#CFLAGS = $(COPT) -Xc +#CFLAGS = $(COPT) + +LDFLAGS = $(LDOPT) -lm + +ECHO = echo +CAT = cat +CP = cp +RMF = rm -f +TAR = tar +CTAGS = ctags +#CTAGS = ctags --langmap=c:.c.h +ZIP = bzip2 +ZIP_EXT = .bz2 +BASENAME = basename +PWD = pwd + +# # # # # + +OBJ = IO.o Str.o atechit.o compile.o deparse.o expr.o hang.o hash.o inc.o \ + kork.o list.o main.o mars.o match.o op.o opt.o parse.o pp.o random.o \ + re.o run.o strhash.o strutil.o sub.o text.o transmogrify.o val.o \ + variable.o venus.o version.o xmalloc.o zz.o + +all: tags ploki + +tags: *.c *.h + $(CTAGS) *.c *.h + +distclean: clean + $(RMF) core examples/core a.out +clean: + $(RMF) *.o ploki +realclean: clean + $(RMF) *.depend Makefile + +remake: clean all + +ploki: $(OBJ) + $(CC) -o ploki $(OBJ) $(LDFLAGS) + +install: ploki + $(CP) ploki '$(INSTDIR)/' + +version.c: version.c.in VERSION + $(CP) version.c.in version.c + $(ECHO) '"'"`$(CAT) VERSION`"'";' >>version.c + +######################################################################## +IO.o: IO.c config.h IO.h Str.h main.h main_io.h xmalloc.h zz.h +Str.o: Str.c config.h Str.h strutil.h xmalloc.h +atechit.o: atechit.c zz.h config.h atechit.h main.h +compile.o: compile.c config.h Str.h compile.h text.h op.h IO.h expr.h \ + re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + main_var.h zz.h +deparse.o: deparse.c config.h Str.h deparse.h text.h op.h IO.h expr.h \ + re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + main_io.h main_label.h mars.h venus.h hash.h zz.h +expr.o: expr.c config.h Str.h expr.h op.h IO.h re.h stack.h xmalloc.h \ + strhash.h val.h kork.h list.h sub.h variable.h hang.h main_io.h \ + main_label.h mars.h venus.h hash.h main_var.h match.h pp.h random.h \ + run.h text.h zz.h +hang.o: hang.c config.h hang.h +hash.o: hash.c config.h hash.h main.h main_opt.h random.h xmalloc.h +inc.o: inc.c config.h inc.h +kork.o: kork.c config.h IO.h Str.h kork.h strutil.h xmalloc.h +list.o: list.c list.h config.h val.h IO.h Str.h kork.h sub.h xmalloc.h +main.o: main.c IO.h config.h Str.h atechit.h compile.h text.h op.h expr.h \ + re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + deparse.h inc.h main.h main_io.h main_label.h mars.h venus.h hash.h \ + main_opt.h main_var.h opt.h parse.h random.h run.h transmogrify.h \ + version.h zz.h +mars.o: mars.c Str.h config.h mars.h op.h IO.h expr.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h +match.o: match.c IO.h config.h Str.h main_io.h main_opt.h match.h re.h \ + val.h kork.h list.h sub.h run.h op.h expr.h stack.h xmalloc.h strhash.h \ + variable.h text.h +op.o: op.c IO.h config.h Str.h expr.h op.h re.h stack.h xmalloc.h \ + strhash.h val.h kork.h list.h sub.h variable.h main_label.h mars.h \ + venus.h hash.h +opt.o: opt.c opt.h +parse.o: parse.c IO.h config.h Str.h inc.h main.h main_label.h mars.h \ + op.h expr.h re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h \ + variable.h venus.h hash.h parse.h text.h +pp.o: pp.c IO.h config.h Str.h kork.h list.h main_io.h main_opt.h match.h \ + re.h val.h sub.h pp.h run.h op.h expr.h stack.h xmalloc.h strhash.h \ + variable.h text.h +random.o: random.c config.h random.h +re.o: re.c config.h IO.h Str.h hash.h main_io.h main_opt.h re.h xmalloc.h \ + zz.h re_block.c.h +run.o: run.c config.h IO.h Str.h atechit.h expr.h op.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h hang.h main.h \ + main_io.h main_label.h mars.h venus.h hash.h main_opt.h run.h text.h \ + zz.h +strhash.o: strhash.c hash.h strhash.h config.h strutil.h xmalloc.h +strutil.o: strutil.c strutil.h config.h +sub.o: sub.c expr.h config.h Str.h op.h IO.h re.h stack.h xmalloc.h \ + strhash.h val.h kork.h list.h sub.h variable.h main_opt.h \ + transmogrify.h text.h +text.o: text.c text.h op.h IO.h config.h Str.h expr.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h +transmogrify.o: transmogrify.c config.h Str.h expr.h op.h IO.h re.h \ + stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + main_label.h mars.h venus.h hash.h text.h transmogrify.h zz.h +val.o: val.c config.h IO.h Str.h val.h kork.h list.h sub.h xmalloc.h +variable.o: variable.c config.h Str.h strhash.h variable.h xmalloc.h +venus.o: venus.c Str.h config.h hash.h op.h IO.h expr.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h venus.h zz.h +version.o: version.c version.h +xmalloc.o: xmalloc.c config.h main.h xmalloc.h +zz.o: zz.c zz.h config.h main.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/README Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,32 @@ +DESCRIPTION + +This is the ploki package. ploki is a programming language defined +by its implementation and designed by accident. There are short example +scripts in the examples/ subdirectory. You might want to copy +syntax/ploki.vim and indent/ploki.vim into your ~/.vim/ directory if you're +using vim; to get automatic filetype detection, create filetype.vim as +described in :help new-filetype and add the following entry: + au BufNewFile,BufRead *.pk setf ploki + +See the files in doc/ for a description of the language. + +BUILDING + +You need a C compiler. Compile all *.c files into a single executable called +'ploki'. That's it. + +If you have make, typing 'make ploki' should invoke your C compiler with the +right arguments. You may need to adjust some configuration variables: CC is +the C compiler used; CFLAGS are default arguments for the compiler; LDFLAGS +are default arguments for the linker. + +You should edit MakeSkel if you're using GNU make, Makefile otherwise. Note +that Makefile is autogenerated by GNU make from MakeSkel and *.depend. + +There is no 'configure' script; ploki is almost completely standard C and +should Just Work(TM). But have a look at config.h if you want to tweak the +autodetection of gcc, C99, presence of /dev/urandom, etc. + + +Have fun! +Lukas Mai
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/Str.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,794 @@ +#include "config.h" +#include "Str.h" +#include "strutil.h" +#include "xmalloc.h" + +#include <ctype.h> +#include <errno.h> +#include <float.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> + +enum {MAGIC = 4}; + +#define OFFSET_OFF(s) \ +do { \ + if ((s)->offset) { \ + memmove((s)->buf - (s)->offset, (s)->buf, (s)->length + 1); \ + (s)->buf -= (s)->offset; \ + (s)->offset = 0; \ + } \ +} while (0) + + +void +St_init(String *s) { + s->buf = xmalloc(s->size = MAGIC, sizeof *s->buf); + s->buf[s->offset = s->length = 0] = '\0'; +} + +void +St_fake(String *s, char *p, size_t n) { + assert(s != NULL); + assert(p != NULL); + s->buf = p; + s->offset = 0; + s->length = s->size = n; +} + +void +St_clear(String *s) { + assert(s != NULL); + if (!s->buf) { + return; + } + xfree(s->buf - s->offset); + s->buf = NULL; + DEBUG(s->offset = s->length = s->size = 0;) +} + +#if 0 +void +(St_zero)(String *s) { + St_zero(s); +} + +char * +(St_ptr)(const String *s) { + return St_ptr(s); +} + +size_t +(St_len)(const String *s) { + return St_len(s); +} +#endif + +static void +St_grow(String *s, size_t n) { + if (s->size - s->offset <= n) { + OFFSET_OFF(s); + if (s->size <= n) { + s->buf = xrealloc(s->buf, n + 1u); + s->size = n + 1u; + } + } +} + +void +St_trunc(String *s, size_t n) { + if (s->length > n) { + s->buf[s->length = n] = '\0'; + } + if (s->size > n + 1 && n >= MAGIC) { + OFFSET_OFF(s); + s->buf = xrealloc(s->buf, n + 1); + s->size = n + 1; + } +} + +#if 0 +int +St_lastchar(const String *s) { + return ST_LASTCHAR(s); +} + +int +St_firstchar(const String *s) { + return ST_FIRSTCHAR(s); +} + +int +St_chop(String *s) { + int tmp; + + if (!s->length) { + return EOF; + } + tmp = (unsigned char)s->buf[s->length - 1]; + s->buf[--s->length] = '\0'; + return tmp; +} +#endif + +int +St_shift(String *s) { + int tmp; + + if (!s->length) { + return EOF; + } + tmp = (unsigned char)s->buf[0]; + ++s->offset; + ++s->buf; + --s->length; + return tmp; +} + + +size_t +St_shiftws(String *s) { + size_t n; + + for (n = 0; n < s->length && isspace((unsigned char)s->buf[n]); ++n) + ; + s->offset += n; + s->buf += n; + s->length -= n; + + return n; +} + +#if 0 +int +St_index(const String *s, size_t n) { + return ST_INDEX(s, n); +} +#endif + +size_t +St_chr(const String *s, int c) { + const char *tmp; + if (!(tmp = memchr(s->buf, c, s->length))) { + return -1; + } + return tmp - s->buf; +} + +#if 0 +size_t +St_rchr(const String *s, int c) { + size_t i; + + for (i = s->length; i; --i) { + if (s->buf[i - 1] == c) + return i - 1; + } + return -1; +} +#endif + +int +St_cmp(const String *s, const String *t) { + return u_cmp(St_ptr(s), St_len(s), St_ptr(t), St_len(t)); +} + +int +St_cmp_m(const String *s, const void *m, size_t n) { + return u_cmp(St_ptr(s), St_len(s), m, n); +} + +#if 0 +int +St_cmp_s(const String *s, const char *tz) { + return u_cmp(St_ptr(s), St_len(s), tz, strlen(tz)); +} +#endif + +#define NCMP(s, m, n) \ +do { \ + return memcmp((s)->buf, m, (s)->length < (n) ? (s)->length : (n)); \ +} while (0) + +#if 0 +int +St_ncmp(const String *s, const String *t) { + NCMP(s, t->buf, t->length); +} +#endif + +int +St_ncmp_m(const String *s, const void *m, size_t n) { + NCMP(s, m, n); +} + +#if 0 +int +St_ncmp_s(const String *s, const char *tz) { + size_t length = strlen(tz); + + NCMP(s, tz, length); +} + +static int +my_memcasecmp(const void *p, const void *q, size_t n) { + const unsigned char *s = p, *t = q; + size_t i; + + for (i = 0; i < n; ++i) { + if (tolower(s[i]) < tolower(t[i])) { + return -1; + } + if (tolower(s[i]) > tolower(t[i])) { + return 1; + } + } + return 0; +} + +#define CASECMP(s, m, n) \ +do { \ + int tmp__; \ + if (!(tmp__ = my_memcasecmp((s)->buf, m, (s)->length < (n) ? (s)->length : (n)))) { \ + if ((s)->length < (n)) \ + return -1; \ + if ((s)->length > (n)) \ + return 1; \ + } \ + return tmp__; \ +} while (0) + +int +St_casecmp(const String *s, const String *t) { + CASECMP(s, t->buf, t->length); +} + +int +St_casecmp_m(const String *s, const void *m, size_t n) { + CASECMP(s, m, n); +} + +int +St_casecmp_s(const String *s, const char *tz) { + size_t length = strlen(tz); + + CASECMP(s, tz, length); +} + +#define NCASECMP(s, m, n) \ +do { \ + return my_memcasecmp((s)->buf, m, n); \ +} while (0) + +int +St_ncasecmp(const String *s, const String *t) { + NCASECMP(s, t->buf, t->length); +} + +int +St_ncasecmp_m(const String *s, const void *m, size_t n) { + NCASECMP(s, m, n); +} + +int +St_ncasecmp_s(const String *s, const char *tz) { + size_t length = strlen(tz); + + NCASECMP(s, tz, length); +} +#endif + +#define STR(s, m, n) \ +do { \ + size_t i__; \ + if ((n) == 0) \ + return 0; \ + if ((s)->length < (n)) \ + return -1; \ + for (i__ = 0; i__ <= (s)->length - (n); ++i__) { \ + if (!memcmp((s)->buf + i__, m, n)) \ + return i__; \ + } \ + return -1; \ +} while (0) + +size_t +St_str(const String *s, const String *t) { + STR(s, t->buf, t->length); +} + +size_t +St_str_m(const String *s, const void *m, size_t n) { + STR(s, m, n); +} + +#if 0 +size_t +St_str_s(const String *s, const char *tz) { + size_t length = strlen(tz); + + STR(s, tz, length); +} +#endif + +#define RSTR(s, m, n) \ +do { \ + size_t i__; \ + if ((n) == 0) \ + return (s)->length; \ + if ((s)->length < (n)) \ + return -1; \ + for (i__ = (s)->length - (n) + 1; i__; --i__) { \ + if (!memcmp((s)->buf + i__ - 1, m, n)) \ + return i__ - 1; \ + } \ + return -1; \ +} while (0) + +#if 0 +size_t +St_rstr(const String *s, const String *t) { + RSTR(s, t->buf, t->length); +} +#endif + +size_t +St_rstr_m(const String *s, const void *m, size_t n) { + RSTR(s, m, n); +} + +size_t +St_rstr_s(const String *s, const char *tz) { + size_t length = strlen(tz); + + RSTR(s, tz, length); +} + +size_t +St_stro_m(const String *s, size_t off, const void *m, size_t n) { + size_t i; + + assert(off <= s->length); + + if (n == 0) { + return off; + } + + if (n > s->length - off) { + return -1; + } + + for (i = off; i < s->length - n; ++i) { + if (memcmp(s->buf + i, m, n) == 0) { + return i; + } + } + return -1; +} + +size_t +St_rstro_m(const String *s, size_t off, const void *m, size_t n) { + size_t i; + + assert(off <= s->length); + + if (n == 0) { + return off; + } + + if (n > s->length) { + return -1; + } + + i = off; + if (i > s->length - n) { + i = s->length - n; + } + + for (; i + 1u; --i) { + if (memcmp(s->buf + i, m, n) == 0) { + return i; + } + } + return -1; +} + +#define CPY(s, m, n) \ +do { \ + if ((s)->size - (s)->offset <= (n)) { \ + OFFSET_OFF(s); \ + if ((s)->size <= (n)) { \ + (s)->buf = xrealloc((s)->buf, (n) + 1); \ + (s)->size = (n) + 1; \ + } \ + } \ + memcpy((s)->buf, m, (s)->length = (n)); \ + (s)->buf[n] = '\0'; \ +} while (0) + +void +St_cpy(String *s, const String *t) { + CPY(s, t->buf, t->length); +} + +void +St_cpy_m(String *s, const void *m, size_t n) { + CPY(s, m, n); +} + +void +St_cpy_s(String *s, const char *tz) { + size_t length = strlen(tz); + + CPY(s, tz, length); +} + +void +St_cpy_c(String *s, int c) { + unsigned char tmp = c; + CPY(s, &tmp, 1); +} + +static void cat(String *s, const void *m, size_t n) { + if (s->size - s->offset <= s->length + n) { + OFFSET_OFF(s); + if (s->size <= s->length + n) { + do { + s->size = s->size / 2 * 3 + 1; + } while (s->size <= s->length + n); + s->buf = xrealloc(s->buf, s->size); + } + } + memcpy(s->buf + s->length, m, n); + s->buf[s->length += n] = '\0'; +} + +void +St_cat(String *s, const String *t) { + cat(s, t->buf, t->length); +} + +void +St_cat_m(String *s, const void *m, size_t n) { + cat(s, m, n); +} + +void +St_cat_s(String *s, const char *tz) { + cat(s, tz, strlen(tz)); +} + +void +St_cat_c(String *s, int c) { + unsigned char tmp = c; + cat(s, &tmp, 1); +} + +#define TAC(s, m, n) \ +do { \ + if ((s)->offset >= (n)) { \ + (s)->buf -= (n); \ + (s)->offset -= (n); \ + } else if ((s)->size <= (s)->length + (n)) { \ + (s)->buf -= (s)->offset; \ + (s)->buf = xrealloc((s)->buf, (s)->length + (n) + 1); \ + (s)->size = (s)->length + (n) + 1; \ + memmove((s)->buf + (n), (s)->buf + (s)->offset, (s)->length + 1); \ + (s)->offset = 0; \ + } else { \ + memmove((s)->buf + (n), (s)->buf, (s)->length + 1); \ + } \ + memcpy((s)->buf, m, n); \ + (s)->length += (n); \ +} while (0) + +#if 0 +void +St_tac(String *s, const String *t) { + TAC(s, t->buf, t->length); +} +#endif + +void +St_tac_m(String *s, const void *m, size_t n) { + TAC(s, m, n); +} + +void +St_tac_s(String *s, const char *tz) { + size_t length = strlen(tz); + + TAC(s, tz, length); +} + +void +St_tac_c(String *s, int c) { + unsigned char tmp = c; + TAC(s, &tmp, 1); +} + +void +St_reverse(String *s) { + size_t i; + char tmp; + + for (i = 0; i < s->length / 2; ++i) { + tmp = s->buf[i]; + s->buf[i] = s->buf[s->length - i - 1]; + s->buf[s->length - i - 1] = tmp; + } +} + +#if 0 +void +St_map(String *s, int (*better)(int)) { + size_t i; + int tmp; + + for (i = 0; i < s->length; ++i) { + tmp = better((unsigned char)s->buf[i]); + if (tmp == EOF) { + s->buf[s->length = i] = '\0'; + return; + } + s->buf[i] = tmp; + } + + while ((tmp = better(EOF)) != EOF) { + if (s->size <= s->length + 1) { + OFFSET_OFF(s); + XREALLOC(s->buf, s->size * 2); + s->size *= 2; + } + s->buf[s->length++] = tmp; + s->buf[s->length] = '\0'; + } +} +#endif + +void +St_grep(String *s, int (*good)(int)) { + size_t r, w; + + for (r = w = 0; r < s->length; ++r) { + if (good((unsigned char)s->buf[r])) { + s->buf[w++] = s->buf[r]; + } + } + s->buf[s->length = w] = '\0'; +} + +void +St_upper(String *s) { + size_t i; + + for (i = 0; i < s->length; ++i) { + s->buf[i] = toupper((unsigned char)s->buf[i]); + } +} + +void +St_lower(String *s) { + size_t i; + + for (i = 0; i < s->length; ++i) { + s->buf[i] = tolower((unsigned char)s->buf[i]); + } +} + +void +St_del(String *s, size_t p, size_t n) { + if (n == 0 || s->length < p) + return; + if (s->length < n || s->length < p + n) { + n = s->length - p; + } + if (p + n == s->length) { + s->buf[p] = '\0'; + } else if (p == 0) { + s->offset += n; + s->buf += n; + } else { + memmove(s->buf + p, s->buf + n + p, s->length - p - n); + } + s->length -= n; +} + +#if 0 +#define INS(s, p, m, n) \ +do { \ + if ((n) == 0 || (s)->length < (p)) \ + return; \ + if ((n) <= (s)->offset) { \ + (s)->offset -= (n); \ + (s)->buf -= (n); \ + memmove((s)->buf, (s)->buf + (n), p); \ + } else { \ + if ((s)->size - (s)->offset <= (s)->length + (n)) { \ + OFFSET_OFF(s); \ + XREALLOC((s)->buf, (s)->length + (n) + 1); \ + (s)->size = (s)->length + (n) + 1; \ + } \ + memmove((s)->buf + (p) + (n), (s)->buf + (p), (s)->length - (p) + 1); \ + } \ + memcpy((s)->buf + (p), m, n); \ + (s)->length += (n); \ +} while (0) + +void +St_ins(String *s, size_t p, const String *t) { + INS(s, p, t->buf, t->length); +} + +void +St_ins_m(String *s, size_t p, const void *m, size_t n) { + INS(s, p, m, n); +} + +void +St_ins_s(String *s, size_t p, const char *tz) { + size_t length = strlen(tz); + + INS(s, p, tz, length); +} + +void +St_ins_c(String *s, size_t p, int c) { + unsigned char tmp = c; + INS(s, p, &tmp, 1); +} +#endif + +void +St_substr(String *l, String *s, size_t p, size_t n, const String *r) { + if (l) { + if (p >= s->length) { + St_zero(l); + } else { + size_t length = n; + + if (p + length > s->length) { + length = s->length - p; + } + St_cpy_m(l, s->buf + p, length); + } + } + + if (r) { + size_t gap = 0; + + if (p + n > s->length) { + if (p > s->length) { + n = 0; + gap = p - s->length; + } else { + n = s->length - p; + } + } + St_grow(s, s->length + r->length - n + gap); + if (gap) { + memset(s->buf + s->length, '\0', gap); + } else if (r->length != n && s->length - p - n) { + memmove(s->buf + p + r->length, s->buf + p + n, s->length - p - n); + } + memcpy(s->buf + p, r->buf, r->length); + s->buf[s->length += r->length - n + gap] = '\0'; + } +} + +#if HAVE_VSNPRINTF_P +size_t +St_xprintf(String *s, const char *fmt, ...) { + va_list ap; + int tmp; + + va_start(ap, fmt); + tmp = vsnprintf(s->buf, s->size, fmt, ap); + va_end(ap); + + if (tmp < 0) { + do { + St_grow(s, s->size * 2); + + va_start(ap, fmt); + tmp = vsnprintf(s->buf, s->size, fmt, ap); + va_end(ap); + } while (tmp < 0); + } else if (tmp + 1u >= s->size) { + St_grow(s, tmp); + s->length = 0; + + va_start(ap, fmt); + tmp = vsnprintf(s->buf, s->size, fmt, ap); + va_end(ap); + + if (tmp < 0) { + s->buf[0] = '\0'; + return -1; + } + } + + return s->length = tmp; +} +#endif + +void +St_num(String *s, double d) { + #if HAVE_VSNPRINTF_P + St_xprintf(s, "%.*g", DBL_DIG, d); + #else + St_grow(s, 255); + s->length = sprintf(s->buf, "%.*g", DBL_DIG, d); + #endif +} + +#if 0 +size_t +St_write(const String *s, FILE *fp) { + return ST_WRITE(s, fp); +} +#endif + +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +size_t +St_read(String *s, FILE *fp, size_t n) { + char buf[4096]; + size_t red; + + St_zero(s); + while (n && !feof(fp) && (red = fread(buf, sizeof *buf, MIN(n, sizeof buf / sizeof *buf), fp))) { + St_cat_m(s, buf, red); + n -= red; + } + return s->length; +} + +#if 0 +int +St_getline(String *s, FILE *fp, int n) { + int c; + + OFFSET_OFF(s); + for (s->length = 0; (c = getc(fp)) != EOF; ++s->length) { + if (s->size <= s->length + 1) { + XREALLOC(s->buf, s->size * 2); + s->size *= 2; + } + s->buf[s->length] = c; + if (c == n) + break; + } + s->buf[s->length] = '\0'; + + return s->length != 0; +} + +void +St_getfile(String *s, FILE *fp) { + size_t tmp; + + OFFSET_OFF(s); + if (s->size <= BUFSIZ) { + XREALLOC(s->buf, BUFSIZ + 1); + s->size = BUFSIZ + 1; + } + + for (s->length = 0; (tmp = fread(s->buf + s->length, 1, BUFSIZ, fp)); ) { + s->length += tmp; + if (s->size <= s->length + BUFSIZ + 1) { + XREALLOC(s->buf, s->size * 2); + s->size *= 2; + } + } + s->buf[s->length] = '\0'; +} +#endif + +size_t +St_hash(const String *s, size_t h) { + return u_hash(St_ptr(s), St_len(s), h); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/Str.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +Str.o: Str.c config.h Str.h strutil.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/Str.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,144 @@ +#ifndef STR_H_ +#define STR_H_ + +#include "config.h" + +#include <stdio.h> + +typedef struct { + char *buf; + size_t length; + size_t size; + size_t offset; +} String; + +void St_init (String *); +void St_fake (String *, char *, size_t); +void St_clear (String *); +#if 0 +void St_zero (String *); +ATTR_PURE +char *St_ptr (const String *); +ATTR_PURE +size_t St_len (const String *); +void St_grow (String *, size_t); +#endif +void St_trunc (String *, size_t); +#if 0 +ATTR_PURE +int St_lastchar (const String *); +ATTR_PURE +int St_firstchar (const String *); +int St_chop (String *); +#endif +int St_shift (String *); +size_t St_shiftws (String *); +#if 0 +ATTR_PURE +int St_index (const String *, size_t); +#endif +ATTR_PURE +size_t St_chr (const String *, int); +#if 0 +size_t St_rchr (const String *, int); +#endif +ATTR_PURE +int St_cmp (const String *, const String *); +ATTR_PURE +int St_cmp_m (const String *, const void *, size_t); +#if 0 +ATTR_PURE +int St_cmp_s (const String *, const char *); +ATTR_PURE +int St_ncmp (const String *, const String *); +#endif +ATTR_PURE +int St_ncmp_m (const String *, const void *, size_t); +#if 0 +ATTR_PURE +int St_ncmp_s (const String *, const char *); +ATTR_PURE +int St_casecmp (const String *, const String *); +ATTR_PURE +int St_casecmp_m (const String *, const void *, size_t); +ATTR_PURE +int St_casecmp_s (const String *, const char *); +ATTR_PURE +int St_ncasecmp (const String *, const String *); +ATTR_PURE +int St_ncasecmp_m (const String *, const void *, size_t); +ATTR_PURE +int St_ncasecmp_s (const String *, const char *); +#endif +ATTR_PURE +size_t St_str (const String *, const String *); +ATTR_PURE +size_t St_str_m (const String *, const void *, size_t); +#if 0 +ATTR_PURE +size_t St_str_s (const String *, const char *); +ATTR_PURE +size_t St_rstr (const String *, const String *); +#endif +ATTR_PURE +size_t St_rstr_m (const String *, const void *, size_t); +ATTR_PURE +size_t St_rstr_s (const String *, const char *); +ATTR_PURE +size_t St_stro_m (const String *, size_t, const void *, size_t); +ATTR_PURE +size_t St_rstro_m (const String *, size_t, const void *, size_t); +void St_cpy (String *, const String *); +void St_cpy_m (String *, const void *, size_t); +void St_cpy_s (String *, const char *); +void St_cpy_c (String *, int); +void St_cat (String *, const String *); +void St_cat_m (String *, const void *, size_t); +void St_cat_s (String *, const char *); +void St_cat_c (String *, int); +#if 0 +void St_tac (String *, const String *); +#endif +void St_tac_m (String *, const void *, size_t); +void St_tac_s (String *, const char *); +void St_tac_c (String *, int); +void St_reverse (String *); +#if 0 +void St_map (String *, int (*)(int)); +#endif +void St_grep (String *, int (*)(int)); +void St_upper (String *); +void St_lower (String *); +void St_del (String *, size_t, size_t); +#if 0 +void St_ins (String *, size_t, const String *); +void St_ins_m (String *, size_t, const void *, size_t); +void St_ins_s (String *, size_t, const char *); +void St_ins_c (String *, size_t, int); +#endif +void St_substr (String *, String *, size_t, size_t, const String *); +#if HAVE_VSNPRINTF_P +ATTR_SPRINTF +size_t St_xprintf (String *, const char *, ...); +#endif +void St_num (String *, double); +#if 0 +size_t St_write (const String *, FILE *); +#endif +size_t St_read (String *, FILE *, size_t); +#if 0 +int St_getline (String *, FILE *, int); +void St_getfile (String *, FILE *); +#endif +ATTR_PURE +size_t St_hash (const String *, size_t); + +#define St_ptr(s) (0 + (s)->buf) +#define St_len(s) (0 + (s)->length) +#define St_zero(s) ((void)((s)->buf[(s)->length = 0] = '\0')) +#define ST_LASTCHAR(s) ((s)->length ? (int)(unsigned char)(s)->buf[(s)->length - 1] : EOF) +#define ST_FIRSTCHAR(s) ((s)->length ? (int)(unsigned char)(s)->buf[0] : EOF) +#define ST_INDEX(s, n) ((size_t)(n) < (s)->length ? (int)(unsigned char)(s)->buf[(size_t)(n)] : EOF) +#define ST_WRITE(s, fp) fwrite((s)->buf, 1, (s)->length, fp) + +#endif /* STR_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/TODO Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,29 @@ +fix write/seek semantics for Z buffers + +add sort function + +add new value type: hashes +@TYPE OF hash : "hash" +- create: +@TAN list; #<key1 value1 key2 value2#> +@SIN list; #<key1 key2#> +@COS list; #<value1 value2#> +- decompose: +@ATAN hash; -> #<key2 value2 key1 value1#> +@ASIN hash; -> #<key2 key1#> +@ACOS hash; -> #<value2 value1#> +- push entries: +hash + hashmod +- pop entries: +hash - hashmod +- replace (-+) entries: +hash _ hashmod +- index: +hash . key +- slice: +hash . #<key1 key2#> +- remove: +hash % key +hash % #<key1 key2#> +- get depth: +hash / key
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/VERSION Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +0.6.5.1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/atechit.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,27 @@ +#include "zz.h" +#include "atechit.h" +#include "main.h" + +#include <stdio.h> +#include <stdlib.h> + +enum {MAGIC = 23}; +static size_t Aused; +static void (*Afunc[MAGIC])(void); + +static void bah(void) { + for (; Aused; Afunc[--Aused]()) + ; +} + +void atechit(void (*f)(void)) { + if (Aused >= sizeof Afunc / sizeof *Afunc) { + NOTREACHED; + } + Afunc[Aused++] = f; + if (Aused == 1 && atexit(bah)) { + fprintf(stderr, "%s: atexit(): error message\n", Prog); + bah(); + exit(EXIT_FAILURE); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/atechit.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +atechit.o: atechit.c zz.h config.h atechit.h main.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/atechit.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,6 @@ +#ifndef ATECHIT_H_ +#define ATECHIT_H_ + +void atechit(void (*)(void)); + +#endif /* ATECHIT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/compile.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,171 @@ +#include "config.h" +#include "Str.h" +#include "compile.h" +#include "expr.h" +#include "main_var.h" +#include "op.h" +#include "text.h" +#include "zz.h" + +#include <assert.h> + +static struct op *end_if(struct text *code, size_t *n) { + for (; *n < code->length; ++*n) { + struct op *const p = code->start[*n]; + switch (p->type) { + case OP_IF: + ++*n; + p->arh.op = code->start[*n]; + p->next = end_if(code, n); + break; + + case OP_ELSE: { + size_t tmp; + tmp = ++*n; + p->next = end_if(code, n); + p->type = OP_NOP; + if (tmp < code->length) { + return code->start[tmp]; + } + return p; + } + + case OP_FI: + p->type = OP_NOP; + return p; + + default: + break; + } + } + + return code->start[0]; +} + +static void resolve(struct expr *e) { + if (!e) { + return; + } + + switch (e->type) { + case literE: + break; + + case varE: + e->v.val = vr_data(Var_plain, e->v.tent); + assert(e->v.val != NULL); + break; + + case varhashE: + e->v.hash = vr_data(Var_hash, e->v.tent); + resolve(e->right); + break; + + case symbolE: + if (e->op == S_ARGV) { + resolve(e->right); + } + break; + + case unopE: + resolve(e->right); + break; + + case binopE: + resolve(e->left.expr); + resolve(e->right); + break; + + case listE: + resolve(e->right); + resolve(e->left.expr); + break; + } +} + +static void op_resolve(struct op *o) { + switch (o->type) { + case OP_NOP: + case OP_GOBACK: + case OP_GOTO: + case OP_HANG: + break; + + case OP_ASSIGN: + case OP_CALL_BACK: + case OP_MODIFY: + case OP_PRINT: + case OP_PUTC: + case OP_TEMP: + resolve(o->arh.expr); + resolve(o->arg); + break; + + case OP_CALL: + case OP_CALL_DYN: + case OP_CLOSE: + case OP_EXIT: + case OP_IF: + case OP_RETURN: + case OP_SYSTEM: + case OP_THROW: + resolve(o->arg); + break; + + default: + NOTREACHED; + break; + } +} + +void compile(struct text *code) { + size_t i; + + for (i = 0; i < code->length; ++i) { + struct op *const p = code->start[i]; + + op_getop(p); + + if (!p->next && p->type != OP_EXIT && i + 1 < code->length) { + p->next = code->start[i + 1]; + } + } + + if (!i) { + struct op tmp; + op_init(&tmp); + text_push(code, &tmp); + } + + vr_freeze(Var_plain); + vr_freeze(Var_hash); + + for (i = 0; i < code->length; ++i) { + struct op *const p = code->start[i]; + + switch (p->type) { + case OP_IF: + ++i; + p->arh.op = code->start[i]; + p->next = end_if(code, &i); + break; + + case OP_ELSE: + ++i; + p->next = end_if(code, &i); + p->type = OP_NOP; + break; + + case OP_FI: + p->type = OP_NOP; + break; + + default: + break; + } + } + + for (i = 0; i < code->length; ++i) { + op_resolve(code->start[i]); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/compile.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +compile.o: compile.c config.h Str.h compile.h text.h op.h IO.h expr.h \ + re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + main_var.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/compile.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,8 @@ +#ifndef COMPILE_H_ +#define COMPILE_H_ + +#include "text.h" + +void compile(struct text *); + +#endif /* COMPILE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/config.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,114 @@ +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#ifdef DEBUGGING + #define DEBUG(x) x + #define DEBUG_P 1 +#else + #define DEBUG(x) + #define DEBUG_P 0 + #define NDEBUG 1 +#endif + +#if defined _WIN32 || defined __WIN32__ || defined WIN32 + #define DIR_END "\\/" +#elif defined __unix__ || defined __linux__ || defined __unix || defined unix + #define DIR_END "/" +#else + /* XXX */ + #define DIR_END 0 +#endif + +#if defined __POSIX__ || defined __unix__ || defined __linux__ || defined __unix || defined unix + #define HAVE_SLEEP_P 1 + #define SLEEP_HEADER <unistd.h> + #define DO_SLEEP pause() +#elif defined _WIN32 || defined __WIN32__ || defined WIN32 + #define HAVE_SLEEP_P 1 + #define SLEEP_HEADER <windows.h> + #define DO_SLEEP Sleep(INFINITE) +#else + #define HAVE_SLEEP_P 0 + #define DO_SLEEP ((void)0) +#endif + +#if defined __linux__ || defined __sun__ || defined __sun + #define HAVE_DEV_URANDOM_P 1 +#else + #define HAVE_DEV_URANDOM_P 0 +#endif + +#ifndef INC_PREFIX + #if defined __unix__ || defined __linux__ || defined __unix || defined unix + #define INC_PREFIX "/usr/local/lib/ploki/" + #else + #define INC_PREFIX 0 + #endif +#endif + +#define INC_PREFIX_LIST \ +{ \ + "", \ + INC_PREFIX, \ + 0 \ +} + +#if defined __STDC_VERSION__ && __STDC_VERSION__ + 0 >= 199901L + #define HAVE_C99_P 1 + #define HAVE_C99(x) x +#else + #define HAVE_C99_P 0 + #define HAVE_C99(x) +#endif + +#ifdef __GNUC__ + #define HAVE_GCC_P 1 + #define HAVE_GCC(x) x +#else + #define HAVE_GCC_P 0 + #define HAVE_GCC(x) +#endif + +#if HAVE_GCC_P + #if __GNUC__ == 2 && __GNUC_MINOR__ >= 7 || __GNUC__ > 2 + #define ATTR(x) __attribute__(x) + #else + #define ATTR(x) + #endif + + #if __GNUC__ == 2 && __GNUC_MINOR__ >= 96 || __GNUC__ > 2 + #define ATTR_MALLOC __attribute__((__malloc__)) + #define ATTR_PURE __attribute__((__pure__)) + #else + #define ATTR_MALLOC + #define ATTR_PURE + #endif +#else + #define ATTR(x) + #define ATTR_MALLOC + #define ATTR_PURE +#endif + +#define ATTR_UNUSED ATTR((__unused__)) +#define ATTR_NORETURN ATTR((__noreturn__)) +#define ATTR_SPRINTF ATTR((__format__(__printf__, 2, 3))) +#define ATTR_CONST ATTR((__const__)) + +#if HAVE_C99_P + #define HAVE_VSNPRINTF(x) x + #define HAVE_VSNPRINTF_P 1 +#elif defined __GLIBC__ + #include <features.h> + #if defined __USE_BSD || defined __USE_ISOC99 || defined __USE_UNIX98 + #define HAVE_VSNPRINTF(x) x + #define HAVE_VSNPRINTF_P 1 + #else + #define HAVE_VSNPRINTF(x) + #define HAVE_VSNPRINTF_P 0 + #endif +#else + #define HAVE_VSNPRINTF(x) + #define HAVE_VSNPRINTF_P 0 +#endif + +#endif /* CONFIG_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/deparse.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,688 @@ +#include "config.h" +#include "Str.h" +#include "deparse.h" +#include "expr.h" +#include "main_io.h" +#include "main_label.h" +#include "text.h" +#include "val.h" +#include "venus.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <stdio.h> +#include <assert.h> + +#if HAVE_VSNPRINTF_P +#define MAKE_LABEL(s, c) \ +do { \ + static unsigned long seq__; \ + St_init(s); \ + St_xprintf(s, "%c%lu", c, seq__++); \ +} while (0) +#else +#define MAKE_LABEL(s, c) \ +do { \ + static unsigned long seq__; \ + St_init(s); \ + St_num(s, seq__++); \ + St_tac_c(s, c); \ +} while (0) +#endif + +ATTR_CONST +static int display(enum t_binop b) { + switch (b) { + case B_SPARK_SPOT: return '!'; + case B_DOUBLE_OH_SEVEN: return '%'; + case B_AMPERSAND: return '&'; + case B_SPARK: return '\''; + case B_SPLAT: return '*'; + case B_INTERSECTION: return '+'; + case B_TAIL: return ','; + case B_WORM: return '-'; + case B_SPOT: return '.'; + case B_SLAT: return '/'; + case B_TWO_SPOT: return ':'; + case B_HYBRID: return ';'; + case B_ANGLE: return '<'; + case B_HALF_MESH: return '='; + case B_RIGHT_ANGLE: return '>'; + case B_U_TURN: return '['; + case B_U_TURN_BACK: return ']'; + case B_SHARK_FIN: return '^'; + case B_FLATWORM: return '_'; + case B_BACKSPARK: return '`'; + case B_EMBRACE: return '{'; + case B_SPIKE: return '|'; + case B_BRACELET: return '}'; + case B_SQIGGLE: return '~'; + default: break; + } + NOTREACHED; +} + +static void dump_str(const String *s) { + size_t i; + + io_write_m(Out, "\"", 1); + for (i = 0; i < St_len(s); ++i) { + const unsigned char c = ST_INDEX(s, i); + if (c != '\\' && c != '"' && isprint(c)) { + io_write_m(Out, &c, 1); + } else { + io_write_m(Out, "\\", 1); + switch (c) { + case '"': + case '\\': io_write_m(Out, &c , 1); break; + case '\a': io_write_m(Out, "a", 1); break; + case '\b': io_write_m(Out, "b", 1); break; + case '\f': io_write_m(Out, "f", 1); break; + case '\n': io_write_m(Out, "n", 1); break; + case '\r': io_write_m(Out, "r", 1); break; + case '\t': io_write_m(Out, "t", 1); break; + case '\v': io_write_m(Out, "v", 1); break; + default: fprintf(io_fp(Out), "%03o", c); break; + } + } + } + io_write_m(Out, "\"", 1); +} + +static void dump_ko(const struct kork *k) { + String tmp; + St_fake(&tmp, (char *)ko_ptr(k), ko_length(k)); + dump_str(&tmp); +} + +static void to_id(struct kork *k, size_t n) { + static char id[] = + "abcdefghijklmnopqrstuvwxyz" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "$" + ; + const size_t base = sizeof id - 1; + do { + ko_cat_c(k, id[n % base]); + n /= base; + } while (n); +} + +static void make_var(struct val *v) { + static size_t seq; + + ko_decouple(v->ko); + to_id(v->ko, seq++); + v->type = V_STR_K; +} + +static void dump_expr(const struct expr *e, int inlist) { + assert(e != NULL); + + switch (e->type) { + case literE: + if (V_EXT_P(e->v.val)) { + fprintf(io_fp(Out), "?%s?", io_name(e->v.val->magic.ext, NULL)); + } else if (V_SUB_P(e->v.val)) { + fprintf(io_fp(Out), "?CODE(%p)?", (void *)e->v.val->magic.sub); + } else if (V_STR_P(e->v.val)) { + dump_ko(e->v.val->ko); + } else if (V_NUM_P(e->v.val)) { + if (e->v.val->num < 0.0) { + fprintf(io_fp(Out), "@NEG %g", -e->v.val->num); + } else { + fprintf(io_fp(Out), "%g", e->v.val->num); + } + } else { + #if 0 + io_write_m(Out, "()", 2); + #endif + } + break; + + case varE: + if (!V_STR_P(e->v.val)) { + assert(e->v.val->type == V_UNDEF); + make_var(e->v.val); + } + io_write_m(Out, ko_ptr(e->v.val->ko), ko_length(e->v.val->ko)); + break; + + case varhashE: { + struct val *tmp; + if (!(tmp = sh_get(e->v.hash, "name", 4))) { + tmp = v_undef(); + make_var(tmp); + sh_put(e->v.hash, "name", 4, tmp); + } + io_write_m(Out, ko_ptr(tmp->ko), ko_length(tmp->ko)); + io_write_m(Out, "(", 1); + dump_expr(e->right, 0); + io_write_m(Out, ")", 1); + break; + } + + case symbolE: + io_write_m(Out, "\\", 1); + switch (e->op) { + case S_NUL: break; + case S_ARG: io_write_m(Out, "@", 1); break; + case S_ARGC: io_write_m(Out, "ARG", 3); break; + + case S_ARGV: + io_write_m(Out, "ARG:", 4); + if (e->right->type == binopE) { + io_write_m(Out, "(", 1); + dump_expr(e->right, 0); + io_write_m(Out, ")", 1); + } else { + dump_expr(e->right, 0); + } + break; + + case S_ERR: io_write_m(Out, "!", 1); break; + case S_EULER: io_write_m(Out, "E", 1); break; + case S_LUDOLF: io_write_m(Out, "PI", 2); break; + case S_MATCH: + fprintf(io_fp(Out), "%lu", (unsigned long)e->left.bonus); + break; + case S_RAND: io_write_m(Out, "?", 1); break; + case S_RESULT: io_write_m(Out, "_", 1); break; + case S_STDIN: io_write_m(Out, "EING", 4); break; + case S_STDOUT: io_write_m(Out, "AUSG", 4); break; + case S_STDERR: io_write_m(Out, "FEHL", 4); break; + + default: NOTREACHED; break; + } + break; + + case unopE: + switch (e->op) { + case F_EXP: io_write_m(Out, "\\E^", 3); break; + case F_LOWER: io_write_m(Out, "\\L" , 2); break; + case F_QUOTE: io_write_m(Out, "\\Q" , 2); break; + case F_RE_ESC: io_write_m(Out, "\\R" , 2); break; + case F_UPPER: io_write_m(Out, "\\U" , 2); break; + case F_MATCH: { + String tmp; + io_write_m(Out, "(", 1); + dump_expr(e->right, 0); + io_write_m(Out, " ~ ", 3); + St_init(&tmp); + re_decompile(e->left.rx, &tmp); + dump_str(&tmp); + St_clear(&tmp); + io_write_m(Out, ")", 1); + return; + } + + default: + io_write_m(Out, "@", 1); + switch (e->op) { + case F_CALL: io_write(Out, &e->left.op->txt); + case F_NUL: break; + case F_ABS: io_write_m(Out, "ABS", 3); break; + case F_ACOS: io_write_m(Out, "ACOS", 4); break; + case F_ASIN: io_write_m(Out, "ASIN", 4); break; + case F_ATAN: io_write_m(Out, "ATAN", 4); break; + case F_ATAN2: io_write_m(Out, "ATAN2", 5); break; + case F_CATCH: io_write_m(Out, "EVAL", 4); break; + case F_CHR: io_write_m(Out, "CHR", 3); break; + case F_COS: io_write_m(Out, "COS", 3); break; + case F_DEFINED: io_write_m(Out, "DEF-P", 5); break; + case F_EOF: io_write_m(Out, "EDD-P", 5); break; + case F_ERROR: io_write_m(Out, "ERR-P", 5); break; + case F_FREEZE: io_write_m(Out, "OMFG", 4); break; + case F_GETC: io_write_m(Out, "GET", 3); break; + case F_GETENV: io_write_m(Out, "ENV", 3); break; + case F_GETS: io_write_m(Out, "LEGS", 4); break; + case F_HANG: { + size_t i; + String tmp; + + St_init(&tmp); + for (St_num(&tmp, i = 1); + ve_findnext(&Venus, &tmp, 0); + St_num(&tmp, ++i)) + ; + fprintf(io_fp(Out), "(%s)", St_ptr(&tmp)); + St_clear(&tmp); + break; + } + case F_INT: io_write_m(Out, "INT", 3); break; + case F_IO: io_write_m(Out, "IO-P", 4); break; + case F_LENGTH: io_write_m(Out, "LENGTH", 6); break; + case F_LOG10: io_write_m(Out, "LG", 2); break; + case F_LOG: io_write_m(Out, "LN", 2); break; + case F_MOEND: io_write_m(Out, "+", 1); break; + case F_MOSTART: io_write_m(Out, "-", 1); break; + case F_NEG: io_write_m(Out, "NEG", 3); break; + case F_NOT: io_write_m(Out, "NOT", 3); break; + case F_NUM: io_write_m(Out, "NUM", 3); break; + case F_OPEN: io_write_m(Out, "APERS", 5); break; + case F_OPENR: io_write_m(Out, "LAPERS", 6); break; + case F_OPENW: io_write_m(Out, "SAPERS", 6); break; + case F_ORD: io_write_m(Out, "ORD", 3); break; + case F_REMOVE: io_write_m(Out, "REMOVE", 6); break; + case F_RENAME: io_write_m(Out, "RENAEM", 6); break; + case F_REVERSE: io_write_m(Out, "REVERSE", 7); break; + case F_SEEK: io_write_m(Out, "SUCH", 4); break; + case F_SIN: io_write_m(Out, "SIN", 3); break; + case F_SQRT: io_write_m(Out, "SPQR", 4); break; + case F_STR: io_write_m(Out, "STR", 3); break; + case F_TAN: io_write_m(Out, "TAN", 3); break; + case F_TELL: io_write_m(Out, "SAG", 3); break; + case F_TYPEOF: io_write_m(Out, "TYPE OF", 7); break; + default: + NOTREACHED; + break; + } + break; + } + if (e->right->type != unopE || e->op == F_NUL) { + io_write_m(Out, "(", 1); + dump_expr(e->right, 0); + io_write_m(Out, ")", 1); + } else { + io_write_m(Out, " ", 1); + dump_expr(e->right, 0); + } + break; + + case binopE: + dump_expr(e->left.expr, 0); + + if (e->op == B_XMATCH) { + io_write_m(Out, " ?o~ ", 5); + } else { + fprintf(io_fp(Out), "%s%c ", &" "[e->op == B_TAIL], display(e->op)); + } + + if (e->right->type == binopE) { + io_write_m(Out, "(", 1); + dump_expr(e->right, 0); + io_write_m(Out, ")", 1); + } else { + dump_expr(e->right, 0); + } + break; + + case listE: + if (!inlist) { + io_write_m(Out, "#<", 2); + } + if (e->right) { + io_write_m(Out, "(", 1); + dump_expr(e->right, 0); + io_write_m(Out, ")", 1); + if (e->left.expr) { + io_write_m(Out, " ", 1); + dump_expr(e->left.expr, 1); + } + } + if (!inlist) { + io_write_m(Out, "#>", 2); + } + break; + + } +} + +static void dump_op(struct op *op) { + switch (op->type) { + case OP_NOP: + io_write_m(Out, "REM", 3); + break; + + case OP_SET_VAL: + case OP_ASSIGN: + io_write_m(Out, "LET ", 4); + if (op->arh.expr) { + dump_expr(op->arh.expr, 0); + io_write_m(Out, " ", 1); + dump_expr(op->arg, 0); + } else { + io_write_m(Out, "(", 1); + dump_expr(op->arg, 0); + io_write_m(Out, ")", 1); + } + break; + + case OP_CALL: + if (op->arh.op) { + fprintf(io_fp(Out), "%s ", St_ptr(&op->arh.op->txt)); + dump_expr(op->arg, 0); + } else { + io_write_m(Out, "LET () ", 7); + dump_expr(op->arg, 0); + if (op->next) { + io_write_m(Out, "\nEND", 4); + } + } + break; + + case OP_CALL_BACK: + io_write_m(Out, "ABRUF (", 7); + dump_expr(op->arh.expr, 0); + io_write_m(Out, ") ", 2); + dump_expr(op->arg, 0); + break; + + case OP_CALL_DYN: + io_write_m(Out, "ANRUF ", 6); + dump_expr(op->arg, 0); + break; + + case OP_CLOSE: + io_write_m(Out, "CLAUDS ", 7); + dump_expr(op->arg, 0); + break; + + case OP_ELSE: + NOTREACHED; + break; + + case OP_EXIT: + if (op->arg->type == literE && !op->arg->v.val->type) { + io_write_m(Out, "END", 3); + } else { + io_write_m(Out, "END ", 4); + dump_expr(op->arg, 0); + } + break; + + case OP_FI: + NOTREACHED; + break; + + case OP_FLUSH: + io_write_m(Out, "FLUSH ", 6); + dump_expr(op->arg, 0); + break; + + case OP_GOBACK: + io_write_m(Out, "GOFOR ", 6); + dump_expr(op->arg, 0); + break; + + case OP_GOTO: + io_write_m(Out, "GOTO ", 5); + dump_expr(op->arg, 0); + break; + + case OP_HANG: + if (St_ptr(&op->txt)) { + fprintf(io_fp(Out), "NEXT %s", St_ptr(&op->txt)); + } else { + String tmp; + MAKE_LABEL(&tmp, '*'); + fprintf(io_fp(Out), "FOR %s NEXT %s", St_ptr(&tmp), St_ptr(&tmp)); + St_clear(&tmp); + } + break; + + case OP_IF: + if (op->arg->type == unopE && op->arg->op == F_NOT) { + io_write_m(Out, "IF ", 3); + dump_expr(op->arg->right, 0); + } else { + io_write_m(Out, "IF @NOT ", 8); + if (op->arg->type == binopE) { + io_write_m(Out, "(", 1); + dump_expr(op->arg, 0); + io_write_m(Out, ")", 1); + } else { + dump_expr(op->arg, 0); + } + } + + if (op->next) { + fprintf(io_fp(Out), "\n NEXT %s\nFI", St_ptr(&op->next->txt)); + } else { + io_write_m(Out, "\n END\nFI", 9); + } + break; + + case OP_MODIFY: + io_write_m(Out, "LET ", 4); + dump_expr(op->arh.expr, 0); + if (op->arh.expr->op == B_XMATCH) { + io_write_m(Out, " ?o~= ", 6); + } else { + fprintf(io_fp(Out), " %c= ", display(op->arh.expr->op)); + } + dump_expr(op->arg, 0); + break; + + case OP_PRINT: + io_write_m(Out, "WUNT ", 5); + if (op->arh.expr) { + dump_expr(op->arh.expr, 0); + io_write_m(Out, " ", 1); + dump_expr(op->arg, 0); + } else if (op->arg->type != binopE) { + dump_expr(op->arg, 0); + } else { + io_write_m(Out, "(", 1); + dump_expr(op->arg, 0); + io_write_m(Out, ")", 1); + } + break; + + case OP_PUTC: + io_write_m(Out, "SET ", 4); + dump_expr(op->arg, 0); + break; + + case OP_RESET: + io_write_m(Out, "RESET ", 6); + dump_expr(op->arg, 0); + break; + + case OP_RETURN: + io_write_m(Out, "KTHX ", 5); + dump_expr(op->arg, 0); + break; + + case OP_SYSTEM: + io_write_m(Out, "# ", 2); + dump_expr(op->arg, 0); + break; + + case OP_TEMP: + io_write_m(Out, "LEET ", 5); + dump_expr(op->arh.expr, 0); + io_write_m(Out, " ", 1); + dump_expr(op->arg, 0); + break; + + case OP_THROW: + io_write_m(Out, "IACS ", 5); + dump_expr(op->arg, 0); + break; + + default: + NOTREACHED; + break; + } +} + +static struct { + size_t length; + size_t size; + struct op **ops; +} seen; + +#define PUSH_SEEN(p) do { \ + if (seen.length >= seen.size) { \ + seen.ops = xrealloc(seen.ops, seen.size *= 2); \ + } \ + seen.ops[seen.length++] = (p); \ +} while (0) + +static int walk(const struct expr *e) { + for (;;) { + switch (e->type) { + case literE: + case symbolE: + return 0; + + case varE: + return 0; + + case varhashE: + e = e->right; + continue; + + case unopE: + if (e->op == F_NUL) { + return 1; + } else if (e->op == F_CALL && !St_ptr(&e->left.op->txt)) { + MAKE_LABEL(&e->left.op->txt, 'f'); + PUSH_SEEN(e->left.op); + } + e = e->right; + continue; + + case binopE: + return walk(e->left.expr) | walk(e->right); + + case listE: + return e->right && (walk(e->right) | (e->left.expr && walk(e->left.expr))); + } + } +} + +static void do_stuff(struct op *op) { + for (; op && !op->line; op = op->next) { + op->line = 1; + + if (St_ptr(&op->txt)) { + fprintf(io_fp(Out), "FOR %s ", St_ptr(&op->txt)); + if (op->type != OP_NOP) { + dump_op(op); + } else { + io_write_m(Out, "REM", 4); + } + io_write_m(Out, "\n", 1); + } else { + dump_op(op); + #if 0 + if (op->type != OP_NOP) + #endif + io_write_m(Out, "\n", 1); + } + + if (op->type == OP_IF) { + if (op->arh.op) { + if (op->arh.op->line) { + fprintf(io_fp(Out), "NEXT %s\n", St_ptr(&op->arh.op->txt)); + } else { + do_stuff(op->arh.op); + } + } + } else if (op->type == OP_CALL) { + if (op->arh.op && !op->arh.op->line) { + PUSH_SEEN(op->arh.op); + } + } else if (op->type == OP_HANG) { + return; + } + + if (op->next) { + if (op->next->line && op->type != OP_IF && op->type != OP_RETURN) { + fprintf(io_fp(Out), "NEXT %s\n", St_ptr(&op->next->txt)); + } + } else if ( + op->type != OP_EXIT && + op->type != OP_CALL && + op->type != OP_CALL_BACK && + op->type != OP_CALL_DYN && + op->type != OP_HANG && + op->type != OP_RETURN + ) { + io_write_m(Out, "END\n", 4); + } + } +} + +enum {MAGIC = 23}; +void deparse(const struct text *t) { + size_t i; + int computed_jumps; + + computed_jumps = 0; + seen.ops = xmalloc(seen.size = MAGIC, sizeof *seen.ops); + seen.length = 0; + + for (i = 0; i < t->length; ++i) { + struct op *op = t->start[i]; + + op->line = 0; + + if ( + op->type == OP_GOBACK || + op->type == OP_GOTO || + op->type == OP_CALL_DYN + ) { + walk(op->arg); + computed_jumps |= 1; + } else if (op->type == OP_CALL_BACK) { + walk(op->arh.expr); + walk(op->arg); + computed_jumps |= 1; + } else if (OP_1ARG_P(op->type)) { + computed_jumps |= walk(op->arg); + if (op->type == OP_CALL && op->arh.op) { + if (!St_ptr(&op->arh.op->txt)) { + MAKE_LABEL(&op->arh.op->txt, 'c'); + } + } + } else if (OP_2ARG_P(op->type)) { + if (op->arh.expr) { + computed_jumps |= walk(op->arh.expr); + } + computed_jumps |= walk(op->arg); + } + + if ( + op->next && + (op->next != t->start[i + 1] || op->type == OP_CALL) && + !St_ptr(&op->next->txt) + ) { + MAKE_LABEL(&op->next->txt, 'x'); + } + } + + if (!computed_jumps) { + do_stuff(t->start[0]); + for (i = 0; i < seen.length; ++i) { + do_stuff(seen.ops[i]); + } + } else { + for (i = 0; i < t->length; ++i) { + struct op *op = t->start[i]; + const String *tmp; + + if ((tmp = ve_label(&Venus, op))) { + if (St_ptr(&op->txt)) { + fprintf(io_fp(Out), " FOR %s\n", St_ptr(&op->txt)); + } + fprintf(io_fp(Out), "%s%s", St_ptr(tmp), &" "[!St_len(tmp)]); + } else { + if (St_ptr(&op->txt)) { + fprintf(io_fp(Out), "FOR %s ", St_ptr(&op->txt)); + } + } + + dump_op(op); + io_write_m(Out, "\n", 1); + + if (op->next && op->next != t->start[i + 1] && op->type != OP_IF) { + fprintf(io_fp(Out), "NEXT %s\n", St_ptr(&op->next->txt)); + } + } + } + xfree(seen.ops); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/deparse.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +deparse.o: deparse.c config.h Str.h deparse.h text.h op.h IO.h expr.h \ + re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + main_io.h main_label.h mars.h venus.h hash.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/deparse.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,8 @@ +#ifndef DEPARSE_H_ +#define DEPARSE_H_ + +#include "text.h" + +void deparse(const struct text *); + +#endif /* DEPARSE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/doc/perl-ploki-regex.txt Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,157 @@ +COMPARISON BETWEEN PERL AND PLOKI REGEXES + + +General: + +ploki doesn't support perl's /cgimosx regex switches: +/c and /g don't make sense in ploki (strings don't have an associated pos()); +/i can be emulated by writing \L str ~ "lowercaseregex"; +/m and /s aren't needed (^, A!, $, Z! match at beginning-of-string, +beginning-of-line, end-of-string, end-of-line respectively; . matches any +character (use '^\n' if you want any character except newline)); +/o is mostly equivalent to ploki's ?o~ operator; +/x is the default in ploki: comments and whitespace are mostly ignored +(except when it's escaped, in a character class, in a quantifier (like "*?" +or ":2,:") or inside "^]", "&]", "?]" and "[number]"). + + + +[Perl] [ploki] + + +Escaping: + +\x x! +No word character is special. No escaped non-word character is special. + + +Alternation: + +foo|bar foo|bar + + +Repetition: + +x* x* +x+ x+ +x? x? +x*? x*? +x+? x+? +x?? x?? +x{n} x:n: +x{n,} x:n,: +x{n,m} x:n,m: + + +Grouping: + +(?:foo) (foo) + + +Character classes: + +[ab0-9\-\]'] 'ab0-9-!]'!' +[^a-z] '^a-z' +. '^\n' +. (with /s) . +[[:alnum:]] '[:alnum:]' + +Ploki provides the following POSIXish character classes (inside an ordinary +character class only): +[:alnum:] alphanumeric char +[:alpha:] alphabetic char +[:cntrl:] control char +[:digit:] digit +[:graph:] printable char (except space) +[:lower:] lowercase char +[:print:] printable char (including space) +[:punct:] punctuation char ([:graph:] without [:alnum:]) +[:space:] whitespace char +[:upper:] uppercase char +[:xdigit:] hex digit +Every POSIXish subclass [:foo:] can be negated by writing [:^foo:] (this is +compatible with Perl). + +In addition there are the following built-in character classes (inside and +outside of user-defined character classes): + + q! (equivalent to '[:alpha:]') + c! (equivalent to '[:cntrl:]') +\d d! (equivalent to '[:digit:]') + l! (equivalent to '[:lower:]') + p! (equivalent to '[:print:]') +\s s! (equivalent to '[:space:]') [1] + u! (equivalent to '[:upper:]') + x! (equivalent to '[:xdigit:]') +\w w! (equivalent to '_[:alnum:]') + +They can be negated by using the corresponding uppercase letter, e.g. D! +matches a non-digit character. + +[1] Perl's \s does not include \v (vertical tab). + + +Independent groups: + +(?>foo) <foo> + + +Capturing: + +(foo) {foo} + + +Backreferences: + +\1, \2, ... 0!, 1!, ... + +Note that ploki's backreferences start with 0 *counting from the right*, +i.e. after a successful match against "{{f}o{o}}", \0 is "foo", \1 is "o" +and \2 is "f". + + +Assertions: + +^ (without /m) ^ +\A ^ +^ (with /m) A! +\z $ +$ (with /m) Z! (roughly) +\b b! +\B B! +(?=foo) [foo&] +(?!foo) [foo^] +(?<=foo) NOT IMPLEMENTED +(?<!foo) NOT IMPLEMENTED + +There's a special assertion that doesn't exist in Perl: [N] succeeds if +N! is set, i.e. if the Nth capturing group succeeded. + + +Selection: + +(?(cond)yes-pattern|no-pattern) [no-pattern|yes-patterncond?] +(?(cond)yes-pattern) [yes-patterncond?] + +Note that in ploki "cond" can be any piece: [oof?] matches "foo" if the next +character is "f". Perl's special case of (?(N)yes|no) can be written as +[no|yes[N]?] in ploki; Perl's m{(\()?[^()]+(?(1)\))} corresponds to ploki's +"{(!}?'^()'+[)![0]?]". + + +Comments: + +(?#foo) [foo#] + + +Debugging: + +perl has a very nice module/command-line option: perl -Mre=debug (or perl +-Mre=debugcolor) will show how perl compiles and matches your regexes. ploki +offers a far less powerful feature: ploki -dr displays a human-readable form +of every regex being compiled. It doesn't show how it matches, however. (On +the other hand I think the regex output of ploki -dr is much more readable +than what perl -Mre=debug produces.) + + +# vi: set tw=76 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/doc/ploki-expr.txt Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,508 @@ + *** THE PLOKI LANGUAGE: EXPRESSIONS *** + + +GENERAL + +ploki is an imperative, unstructured language, similar to BASIC. Some of its +features are borrowed from Perl. ploki's data structures are fully dynamic, +i.e. they resize themselves when necessary. Strings know their length and +may contain binary data. + + +VALUES + +There are six types of values: +1. String: A (possibly empty) sequence of characters. + Any value can be converted to a string. +2. Number: A (double precision) floating point number. + Any value can be converted to a string. +3. IO handle: Can be read from or written to. +4. List: A (possibly empty) sequence of values. +5. Bound expression: See @OMFG below. +6. Undefined. + +Values aren't necessarily one thing or another. There's no place to declare +a variable to be of type "string", type "number", or anything else. In fact, +you can't declare variables at all. Every variable you use is initialized +with the undefined value ("undef" for short). + + +Truth + +0, "0", "", #<#> and undef are false. Any other value is true. + + +Conversions + +Conversions happen as follows: + * number -> string: decimal floating point, the "normal" way + * IO handle -> string: filename + * list -> string: concatenation of the stringified list elements + * bound expression -> string: undefined results + * undef -> string: "" (the empty string) + + * string -> number: initial whitespace is skipped, the rest of the string + is interpreted as a decimal floating point number + (as done by strtod()) + * IO handle -> number: undefined results + * list -> number: sum of the numified list elements + * bound expression -> number: undefined results + * undef -> number: 0.0 + + +Constructors + +Anything starting with a digit or a period followed by a digit is taken to +be the beginning of a number (again, as parsed by strtod(), which means that +scientific notation (e.g. 1e-23) is allowed). String literals start with '"' +and end with '"' or end-of-line. The following escape sequences are +recognized: + + \OOO octal char (where OOO matches [0-7]{1,3}) + \xXX hex char (where XX matches [0-9a-fA-F]{1,2}) + \a alarm + \b backspace + \f form feed + \n newline + \r carriage return + \t tab + \v vertical tab + + \cX the character resulting from (toupper(X) + 64) % 128 + (this depends on the character set used) + + \V<value> + The stringified result of evaluating <value>. In other words, this + can be used to interpolate expressions in strings. + Example: "2 + 2 = \V(2 + 2)" yields "2 + 2 = 4". + + +Lists start with #< and end with #> or end-of-line. Example: #<2 +1 (3 +4)#> +is equivalent to #<2 1 7#>. + +The empty value yields undef: `-2' is parsed as ` - 2', undef is converted +to 0.0, and the result is 0.0 - 2.0, which is -2. + + +Special symbols + +There are the following special symbols, similar to Perl's punctuation +variables: + + * \N (where N is a non-empty sequence of digits) + Contains the substring that was matched by the Nth capturing group in + the previous pattern match. + * \! + If used numerically, yields the current value of C's errno variable, or + in other words, if a system or library call fails, it sets this + variable. If used as a string, yields the corresponding system error + string (i.e. strerror(errno)). + * \? + Yields a random number in the range [0,1). + * \_ + Contains the return value of the last command. + * \@ + The argument the current function was called with. + * \ARG + Number of command line options (C's argc). + * \AUSG + The standard output IO handle (open mode: "WF"). + * \EING + The standard input IO handle (open mode: "RZ"). + * \E + Euler's number: 2.718281828... + * \FEHL + The standard error IO handle (open mode: "WF"). + * \PI + pi: 3.14159265... + * \ + undef + + +VARIABLES + +There are two kinds of variables: plain variables and subscripted variables. +A plain variable has the form [A-Za-z$]+, i.e. one or more alphabetic +characters (where '$' is considered alphabetic). A subscripted variable +looks like a plain variable immediately followed by an opening paren "(", an +expression (the result of which is converted to a string) and possibly a +closing paren ")". + + +UNARY OPERATORS + +Each unary operator takes a value and returns a value. The only exception is +@OMFG, which is more a constructor than an operator. + + * \ARG: + Takes an integer and returns the corresponding command line argument + (like C's argv[]). + * \L + Returns a lowercased version of its operand (like Perl's lc). + * \Q + Returns its operand with all non-word characters backslashed, i.e. any + character not matching [a-zA-Z0-9_] will be preceded by a \ in the + returned string (like Perl's quotemeta). + * \R + Returns its operand with all non-word characters regex-escaped, i.e. any + character not matching [a-zA-Z0-9_] will be followed by a ! in the + returned string (like s/(\W)/$1!/g in Perl). + * \U + Returns an uppercased version of its operand (like Perl's uc). + * @+ + For an operand N, returns the offset of the character after the portion + of the string matched by the Nth capturing group in the last pattern + matching. + * @- + For an operand N, returns the offset of the portion of the string + matched by the Nth capturing group in the last pattern matching. + * @ABS + Returns the absolute value of its operand. + * @ACOS + Returns the arc cosine of its operand. + * @APERS + Takes a list of two elements, a filename and a mode string. Opens the + specified file and returns an IO handle or undef on error. If the mode + string contains "A", the file is created if necessary and opened for + appending (i.e. every write goes to the end of the file); if the mode + string contains "W", the file is truncated/created and opened for + writing; otherwise the file is opened for reading, and the open fails if + the file doesn't exist. If the mode string contains "+", reading is + added for "A" and "W", and writing otherwise. "R+" is almost always + preferred for read/write access; "W+" would clobber the file first. The + resulting IO handle defaults to text mode; add "B" to open the file in + binary mode. Adding "F" turns on autoflush mode, i.e. the stream is + flushed after every write. If the file is opened for reading and the + mode string contains "Z", the resulting stream can be used with the + regex match operator (~). + * @ASIN + Returns the arc sine of its operand. + * @ATAN + Returns the arc tangent of its operand. + * @ATAN2 + Takes a list of two elements #<y x#> and returns the arc tangent of x + and y. It is similar to @ATAN (y / x), except that the signs of both + arguments are used to determine the quadrant of the result. + * @CHR + Takes an integer and returns the character represented by that number in + the character set. + * @COS + Returns the cosine of its operand. + * @DEF-P + Returns "" if its operand is undef, 1 otherwise. + * @EDD-P + Returns 1 if the end-of-file indicator for its operand (which must be an + IO handle) is set, "" otherwise. + * @ENV or \ENV + Returns the value of the specified environment variable. + * @ERR-P + Returns 1 if the error indicator for its operand (which must be an IO + handle) is set, "" otherwise. + * @EVAL + Evaluates and returns its operand. If an exception is thrown during the + evaluation of its operand, assigns the exception value to \_ and returns + undef. + * @GET + Takes an IO handle, reads one character, and returns its numeric value or + -1 on end-of-file or error. + * @INT + Returns the integer portion of its operand. + * @IO-P + Returns 1 if its operand is an IO handle, "" otherwise. + * @LAPERS + Takes a filename, opens it for reading, and returns the resulting IO + handle or undef on failure. Equivalent to @APERS #<filename "RB"#>. + * @LEGS + Takes an IO handle, reads a line and returns it. Returns "" on + end-of-file and undef on error. + * @LENGTH + If passed a list, returns the number of elements; otherwise, returns the + length of its operand in characters. + * @LG + Returns the base-10 logarithm of its operand. + * @LN + Returns the natural logarithm (base e) of its operand. + * @NEG + Performs arithmetic negation. + * @NOT + Returns 1 if its operand is false, "" otherwise. + * @NUM + Converts its operand to a number. + * @ORD + Returns the numeric value of the first character of its operand. + * @OMFG + Does not evaluate its operand but wraps it up in a bound expression by + replacing all variables by their current value. + * @REMOVE + Tries to remove the specified file. Returns 1 for success, "" for + failure. + * @RENAEM + Takes a list of two filenames #<OLD NEW#> and tries to rename OLD to + NEW. Returns 1 for success, "" for failure. + * @REVERSE + If passed a list, returns a list consisting of the elements of the + original list in the opposite order. Otherwise, returns a string with + all the characters in the opposite order. + * @SAG + Returns a value representing the current file position of its operand + (which must be an IO handle) suitable as the second argument of @SUCH. + If the file was opened in binary mode, this is the number of bytes from + the beginning of the file. + * @SAPERS + Takes a filename, opens it for writing, and returns the resulting IO + handle or undef on failure. The file is created if it doesn't exist and + truncated to length 0 otherwise. Equivalent to @APERS #<filename + "WBF"#>. + * @SIN + Returns the sine of its operand. + * @SQRT + Returns the square root of its operand. + * @STR + Converts its operand to a string. + * @SUCH + Takes a list of two or three elements, #<IO POS WHENCE#>. WHENCE + defaults to 0 if omitted. Sets the current file position of IO (which + must be an IO handle) to POS (relative to WHENCE). WHENCE must be one of + 0 (beginning of the file), 1 (current position) or 2 (end of file). If + IO is in text mode, POS must be a value returned by @SAG and WHENCE must + be 0, or POS must be 0. If IO is in binary mode, the new position + (measured in bytes from the beginning of the file) is obtained by adding + POS to the position specified by WHENCE. In this case POS=0 and WHENCE=2 + may not work, depending on your C library. + * @TAN + Returns the tangent of its operand. + * @TYPE OF + Returns a string describing the type of its operand: "string" for + strings, "number" for numbers, "stream" for IO handles, "list" for + lists, "stuff" for bound expressions, "nothing" for undef. + * @<label> (where <label> is a static label) + Calls the static label <label> with its operand. + * @ + Calls the dynamic label specified by its operand. + + +BINARY OPERATORS + +Some of the operators (marked with (SL)) below double as string and list +operators. They do the same thing with strings and lists by treating strings +as lists of characters. Boolean and comparison operators return 1 for true +and "" for false. + + _ (SL) If given two lists, it concatenates them. Otherwise, it converts + its operands to strings and concatenates them. + + + Adds two numbers. + - Subtracts two numbers. + * Multiplies two numbers. + / Divides two numbers. + % Returns the modulus (remainder from division) of two numbers. + ^ Exponentiation. + + [ (SL) Given a string/list B and an integer N, returns the + substring/sublist of B starting at index N. Negative indices start from + the end of the string/list. + Example: "foo" [ 1 yields "oo"; "foobar" [ -2 yields "ar". + + ] (SL) Given a string/list B and an integer N, returns the + substring/sublist of B having a length of N. Negative lengths start + from the end of the string/list. + Example: "foo" ] 1 yields "f"; "foobar" ] -2 yields "foob" + + < Numeric less than. + > Numeric greater than. + { (SL) String/list less than. + } (SL) String/list greater than. + = Numeric equality. + ! Numeric inequality. + : (SL) String/list equality. + ; (SL) String/list inequality. + + & Logical and. + | Logical or. + + ~ Pattern match. The left operand is the string or IO stream to be + matched, the right operand is a string forming a regular expression + (see PATTERNS below). On failure, "" is returned. On success, returns + the position of the match and sets \_ to the position after the match. + + ?o~ Similar to ~ above, except that the right operand is only evaluated the + first time it is executed. This means that (foo ?o~ bar) won't see any + changes to bar after the first match attempt (like /o in Perl). + + ` Given a number X and an integer N (which must be in the range 2 .. 36), + returns a string representation of X in base N. + ' Given a string S and an integer N (which must be in the range 2 .. 36), + interprets S as a number in base N and returns the result. + + (the empty operator) or + . (SL) This one is really three different operators, depending on the + type of its left operand: + - IO handle: Attempts to read and return N bytes where N is the right + operand. + - Bound expression: Evaluates the bound expression with \@ temporarily + set to the right operand. + - String/list: Returns the element at the index specified by the right + operand. + + , Returns its right operand. + + +PATTERNS + +The ~ operator tries to match a string or IO handle against a pattern. A +match succeeds if the pattern matches a substring of the matched string. +When matching an IO handle (which must have been opened with "Z"), the +matched characters are removed from the input stream if the match succeeds. + +Whitespace in the pattern is mostly ignored (that is, the pattern " a b" is +equivalent to "ab"). Exceptions are marked [S] below. There is a special +kind of "whitespace": everything between "[" and "#]" is ignored (except for +"!"s), so you can write "foo [ a comment with [! in it #] bar" instead of +"foobar". + +A search pattern consists of one or more branches, separated by "|". It +succeeds if one of its branches succeeds. The branches are tried in the +order they're specified. + +A branch is a (possibly empty) sequence of pieces. It succeeds if all of the +pieces match in turn. + +A piece is an atom, possibly followed by a quantifier. A missing quantifier +means the atom must match exactly once. + +A quantifier is one of the following (N, M are nonnegative integers): + * 0 or more of the preceding atom (greedy) + *? 0 or more of the preceding atom (nongreedy) [S] + + 1 or more of the preceding atom (greedy) + +? 1 or more of the preceding atom (nongreedy) [S] + ? 0 or 1 of the preceding atom (greedy) + ?? 0 or 1 of the preceding atom (nongreedy) [S] + :N: exactly N of the preceding atom [S] + :N:? exactly N of the preceding atom [S] + :N,: N or more of the preceding atom (greedy) [S] + :N,:? N or more of the preceding atom (nongreedy) [S] + :N,M: at least N but not more than M of the preceding atom (greedy) + [S] + :N,M:? at least N but not more than M of the preceding atom (nongreedy) + [S] + +An atom is either a character class, an assertion, a selection, a subgroup, +a capturing group, a backreference, an independent subgroup, an +abbreviation, an escaped character, or an ordinary character. + +A character class is either a built-in class or a custom class. A built-in +class is one of the following: + . a character + c! a control character + C! a non-control character + d! a digit + D! a non-digit + l! a lowercase character + L! a non-lowercase character + p! a printable character + P! a non-printable character + q! an alphanumeric character + Q! a non-alphanumeric character + s! a space character + S! a non-space character + u! an uppercase character + U! a non-uppercase character + w! a word character, i.e. one of a-zA-Z0-9_ + W! a non-word character + x! a hex digit, i.e. one of 0-9a-fA-F + X! a non-hex character + +[S] A custom class is a (possibly empty) sequence of characters, enclosed in +'' (single quotes). It matches one of the listed characters, unless the +first character is '^', in which case it matches one of the not listed +characters. Whitespace is significant inside character classes. A range of +characters can be specified by putting a '-' between the endpoints. In +addition, all built-in classes listed above (except for .) and the following +subclasses are available: + + [:alnum:] equivalent to q! + [:^alnum:] equivalent to Q! + [:alpha:] equivalent to a! + [:^alpha:] equivalent to A! + [:cntrl:] equivalent to c! + [:^cntrl:] equivalent to C! + [:digit:] equivalent to d! + [:^digit:] equivalent to D! + [:graph:] equivalent to '^P! ', i.e. any printable character except space + [:^graph:] equivalent to 'P! ', i.e. any non-printable character or space + [:lower:] equivalent to l! + [:^lower:] equivalent to L! + [:print:] equivalent to p! + [:^print:] equivalent to P! + [:punct:] equivalent to '^P!q! ', i.e. any non-alphanumeric, non-space + printable character + [:^punct:] equivalent to 'P!q! ', i.e. a non-printable character, an + alphanumeric character or space + [:space:] equivalent to s! + [:^space:] equivalent to S! + [:upper:] equivalent to u! + [:^upper:] equivalent to U! + [:xdigit:] equivalent to x! + [:^xdigit:] equivalent to X! + +To include a literal ^, !, - or ' in a character class, escape it with a +following !. Example: '!!'!' is a class that matches ! or '. + +An assertion is something that doesn't consume parts of the matched string, +i.e. it matches with zero length. There are built-in assertions and custom +assertions. A built-in assertion is one of the following: + + ^ at beginning of string + $ at end of string + A! at beginning of line + Z! at end of line + b! at a word boundary + B! not at a word boundary + +A custom assertion is either a positive assertion, a negative assertion or a +backreference check. A positive assertion consists of "[", followed by a +pattern, followed by "&]" [S]. It succeeds (without consuming parts of the +matched string) if the enclosed pattern succeeds. A negative assertion +consists of "[", followed by a pattern, followed by "^]" [S]. It succeeds if +the enclosed pattern fails. A backreference check consists of "[", followed +by a number, followed by "]" [S]. It succeeds if the corresponding capturing +group succeeded. + +A selection consists of "[", optionally followed by a pattern followed by +"|", followed by a branch, followed by an atom, followed by "?]" [S]. It +matches as follows: First the atom is tried. If it matches, the preceding +branch is tried; otherwise matching continues with the preceding pattern if +specified. In other words, it looks like +"[no-pattern|yes-pattern(conditition)?]" or "[yes-pattern(condition)?]". +Example: "{(!}?'^()'+[)![0]?]" matches a chunk of non-parentheses, possibly +included in parentheses themselves. + +A subgroup is a parenthesized pattern. It succeeds if the enclosed pattern +succeeds. + +A capturing group is a pattern surrounded by "{" and "}". It succeeds if the +enclosed pattern succeeds. As a side effect, it sets \N, @-(N) and @+(N) +where N is the number of the capturing group. Capturing groups are numbered +from the right, counting the closing braces (starting with 0). + +A backreference is N! where N is a non-negative integer. It succeeds if it +can match the same substring that was matched by the Nth capturing group. + +An independent subgroup is a pattern, surrounded by "<" and ">". It succeeds +if the enclosed pattern succeeds, but when it does, it won't backtrack in +the enclosed pattern. + +An abbreviation is a (possibly empty) sequence of characters surrounded by +"`" and "`". All metacharacters lose their special meaning inside an +abbreviation, except for ` (which marks the end of the abbreviation) and ! +(which escapes the previous character, as usual). `abcd` is equivalent to +(a(b(cd?)?)?)?, i.e. an abbreviation for x matches the longest possible +initial substring of x. + +[S] An escaped character is a special character like "!" or "+" (or +whitespace), followed by an "!". It matches that character literally. + +An ordinary character matches itself. + + +# vi: set tw=76 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/doc/ploki-ins.txt Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,9 @@ + ### THE PLOKI LANGUAGE: INSERT ### + + +The "INSERT( DA) file HERE" directive includes the contents of "file" +verbatim at that point in the program. If " DA" is specified, "file" is +taken to be an absolute filename; otherwise, it is searched for in the +INC_PREFIX_LIST specified in config.h at compile time. On MS Windows and +Unix-like systems it defaults to the directory where the program is located; +otherwise it's empty.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/doc/ploki-instr.txt Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,97 @@ + %%% THE PLOKI LANGUAGE: INSTRUCTIONS %%% + + +Execution starts at the first line of the program. Instructions are executed +in the order they appear in the program. Executing end-of-file is equivalent +to END 0, i.e. successful exit. + +There are the following instructions ([X] means X is optional): + + * LET [Variable] Expression + Evaluates Expression and assigns the result to Variable (or \_ if + Variable is omitted). + + * WUNT [Value] Expression + Writes the result of Expression to Value (which must yield an IO handle) + if specified; otherwise it writes to \AUSG (standard output). Sets \_. + + * IF Expression + Jumps to the corresponding ELSE or FI instruction if Expression yields + false. "Corresponding" means it skips intervening IF-FI groups. If no + ELSE or FI can be found, jumps to the beginning of the program. + + * ELSE + Jumps to the corresponding FI instruction if present or to the beginning + of the program otherwise. + + * FI, END IF + Serves as an end point for IF and ELSE jumps. Does nothing. + + * GOTO Expression + Jumps to the next line whose dynamic label is equal to the result of + Expression. Search wraps around at end-of-file. + + * GOFOR Expression + Jumps to the previous line whose dynamic label is equal to the result of + Expression. Search wraps around at beginning-of-file. + + * CLAUDS Expression + Closes the IO handle returned by Expression. Sets \_. + + * SET [Value] Expression + Writes the character represented by the number returned by Expression to + the IO handle specified by Value (or \AUSG if Value is omitted). Sets + \_. + + * #! + A comment. The rest of the line is ignored. + + * REM + A comment. The rest of the line is ignored. REM comments may be nested. + + * # Expression + Calls the C function system(3) with the result of Expression, i.e. runs + the local command line interpreter. Sets \_. + + * NEXT Label + Jumps to Label, which must be a static label. + + * ANRUF Expression + Calls the next instruction with the dynamic label specified by + Expression, i.e. it remembers the instruction it came from. Search wraps + around at end-of-file. Sets \_ on returning. + + * ABRUF Value Expression + Calls the previous instruction with the dynamic label specified by + Value, passing Expression as argument. Search wraps around at + beginning-of-file. Sets \_ on returning. + + * KTHX Expression + Returns Expression from the current call. Equivalent to END if not in a + call. + + * LEET [Variable] Expression + Similar to LET but the old value of Variable (if any) is restored at the + following KTHX. + + * END Expression + Exits the program with a status of Expression. If Expression is -1, + exits with EXIT_FAILURE. + + * IACS Expression + Throws Expression as an exception. + + * FLUSH Expression + Forces a write of all buffered data for the IO handle returned by + expression, which must be opened for writing. Sets \_. + + * RESET Expression + Clears the end-of-file and error flags for the IO handle returned by + Expression. + + * Label Expression + Calls the instruction with the static label Label, setting \@ to + Expression. Sets \_ on returning. + + * Expression + Prints the result of Expression to \AUSG.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/doc/ploki-prog.txt Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,19 @@ + ### THE PLOKI INTERPRETER ### + +Usage: ./ploki [OPTIONS] [FILE [ARG]...] + +Available options: + + -h print a short help message and exit + -v print version and configuration info and exit + -MO=Deparse turn the compiled program back into ploki source + -O disable any optimizations + -d FLAGS print debugging info + FLAGS must be one or more of the following: + h hash tables + o opcode execution + r regex engine + +Interpret FILE as ploki program and execute it, unless -MO=Deparse is +specified. With no FILE, or when FILE is -, read from standard input. +Any ARGs are passed through to the program.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/doc/ploki-syn.txt Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,137 @@ + === THE PLOKI LANGUAGE: SYNTAX === + + +GENERAL STRUCTURE: + +A ploki program consists of a (possibly empty) sequence of ordinary lines or +include directives. + +An include directive is either absolute or relative. An absolute include +directive is optional whitespace, followed by "INSERT DA", followed by one +or more non-whitespace characters, followed by "HERE", followed by optional +whitespace. A relative include directive is optional whitespace, followed by +"INSERT", followed by optional whitespace, followed by one or more +non-whitespace characters, followed by "HERE", followed by optional +whitespace. + +An ordinary line consists of optional whitespace, a label, and stuff. + +Stuff consists of an instruction and the rest of the line. Any "??/\n" +sequence (that's four characters: ?, ?, / and newline) in stuff is ignored +unless the instruction is REM. +Example: +WUNT "foo??/ +bar" +is equivalent to +WUNT "foobar" +. + +There are two types of labels, static and dynamic. + * A static label consists of the three letters "FOR", whitespace and a + non-empty sequence of non-whitespace characters which hasn't been defined + as a static label yet, followed by optional whitespace. + * A dynamic label consists of a possibly empty sequence of digits, followed + by optional whitespace. + + +INSTRUCTIONS: + +These are the available instructions (in no particular order): + + * "#!": + A comment. The rest of the line is ignored. + + * "REM": + A comment. The rest of the line is ignored but scanned for "REM" ... + "\n" pairs. In other words, REM comments may nest. + + * "LET", "LEET": + Assignment. The rest of the line is an optional lvalue, followed by an + expression. + + * "WUNT", "SET": + Output. The rest of the line is an optional value, followed by an + expression. + + * "IF": + Conditional jump. The rest of the line starts with an expression. + + * "ELSE": + Jump. The rest of the line is ignored. + + * "FI", "END IF": + Jump target. The rest of the line is ignored. + + * "#": + System call. The rest of the line starts with an expression. + + * "GOTO", "GOFOR": + Computed jump. The rest of the line starts with an expression. + + * "NEXT": + Static jump. The rest of the line must start with the name of a static + label. + + * "ANRUF": + Computed call. The rest of the line starts with an expression. + + * "ABRUF": + Computed call. The rest of the line is a value, followed by an + expression. + + * "END": + Exit. The rest of the line starts with an expression. + + * "KTHX": + Return. The rest of the line starts with an expression. + + * "CLAUDS": + Close. The rest of the line starts with an expression. + + * "FLUSH": + Flush. The rest of the line starts with an expression. + + * "RESET": + Clear error/eof flags. The rest of the line starts with an expression. + + * "IACS": + Throw. The rest of the line starts with an expression. + + * Anything else: + Output. The rest of the line starts with an expression. + + +EXPRESSION SYNTAX: + +An expression either an expression followed by a binary operator and a +value, or a value. A value is either an lvalue or an rvalue. An lvalue is a +plain variable or a hash variable. An rvalue is a special symbol, a +constructor, a unary operator followed by a value, a binary operator +followed by a value, or a "(", followed by an expression, optionally +followed by ")". A plain variable is an identifier; a hash variable is an +identifier, immediately followed by "(", an expression and an optional ")". +An identifier is a non-empty sequence of "a" .. "z", "A" .. "Z", "$". + +Special symbols: \<DIGITS> (where <DIGITS> is a non-empty sequence of +digits), \!, \?, \_, \@, \ARG, \AUSG, \EING, \E, \FEHL, \PI, \, (the empty +string). + +A constructor is +- a floating point number as recognized by strtod() -OR- +- a string starting with '"', followed by a 0 or more of the following: + "\V" followed by a value, or "\" followed by a non-newline character, or a + non-'"' character; + optionally terminated by '"' -OR- +- a list starting with "#<", followed by 0 or more values, optionally + terminated by "#>". + +Unary operators: \ARG:, \ENV, \L, \Q, \R, \U, @-, @+, @ABS, @ACOS, @APERS, +@ASIN, @ATAN, @ATAN2, @CHR, @COS, @DEF-P, @EDD-P, @ENV, @ERR-P, @EVAL, @GET, +@INT, @IO-P, @LAPERS, @LEGS, @LENGTH, @LG, @LN, @NEG, @NOT, @NUM, @ORD, +@OMFG, @REMOVE, @RENAEM, @REVERSE, @SAG, @SAPERS, @SIN, @SQRT, @STR, @SUCH, +@TAN, @TYPE OF, @<LABEL> (where <LABEL> is the name of a static label), @. + +Binary operators (separated by spaces): ++ - * / % ^ _ < [ { > ] } = ! : ; & | ~ ` ' . , ?o~ + +# vi: set tw=76 et:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/SOME FILE Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +REM vi: set ft=ploki: +GOTO 666 +FOR foo KTHX \@ * 2 +666 #!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/arg.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,7 @@ +#!../ploki +LET i @NEG 1 +FOR arg LET i i+1 +IF i < \ARG + WUNT ("arg "_ i _ " = " _ \ARG:i _ "\n") + NEXT arg +FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/beer.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,10 @@ +#!../ploki +LET bottle("") " bottles of beer" +LET bottle(1) " bottle of beer" +LET n 99 +FOR beer WUNT (n_bottle(n=1)_" on the wall,\n"_n_bottle(n=1)_",\ntake one down and pass it around,\n") +LET n n-1 +WUNT (n_bottle(n=1)_" on the wall.\n\n") +IF n + NEXT beer +FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/bf2c.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,52 @@ +#!/usr/local/bin/ploki +REM brainfuck to c translator + +INSERT perl-util.pk HERE + +LET tr("[") "while (*p) {\n" +LET tr("]") "}\n" +LET tr("<") "--p;\n" +LET tr(">") "++p;\n" +LET tr("+") "++*p;\n" +LET tr("-") "--*p;\n" +LET tr(".") "putchar(*p);\n" +LET tr(",") "*p = getchar();\n" +LET tr("0") "*p = 0;\n" + +"#include <stdio.h>\nint main(void) {\nstatic unsigned char A[30000];\nunsigned char *p = A;\n" _ @s///g #<@clean @balanced @s///g #<@input \ARG:1 "'^[]<>.,+-'+" ""#> "'[]<>.,0+-'" @OMFG tr(\@)#> _ "return 0;\n}\n" +END + +FOR clean LEET s \@ + LEET $c$ 0 + 10 LET s @s///g #<@s///g #<s "{^|]!}[!'^[]'*]!" @OMFG @countrepl \0#> "{(^|]!)[!'^]'*}[!'^[]'*]!" @OMFG @countrepl \0#> + IF $c$ + LET $c$ 0 + GOFOR 10 + FI +KTHX @s///g #<s "[!'+-']!" "0"#> + +FOR countrepl LET $c$ += 1 +KTHX \@ + +FOR balanced LEET s @s///g #<\@ "'^[]'+" ""#> + LEET $c$ 0 + 10 LET s @s///g #<s "[!]!" @OMFG @countrepl ""#> + IF $c$ + LET $c$ 0 + GOFOR 10 + FI + IF s ; "" + IACS "\V\ARG:0: error: unbalanced brackets + FI +KTHX \@ + +FOR input LEET fh + IF @TYPE OF \@ : "nothing" + LET fh \EING + ELSE + LET fh @LAPERS \@ + IF @NOT fh + IACS "\V\ARG:0: \V\@: \V\! + FI + FI +KTHX fh . @NEG 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/calc.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,192 @@ +#!../ploki +FOR main "> " + LET line @LEGS \EING + IF line ; "" + LET px @parse line + LET s @shiftws (px . 1) + IF s [ -1 : "\n" + LET s ]= -1 + FI + IF @TYPE OF (px . 0) : "list" + IF s : "" + @eval (px . 0) _" + ELSE + "error: trailing garbage at --> \Vs + FI + ELSE + IF s : "" + LET s " at end of input" + ELSE + LET s " at --> \Vs" + FI + "error: \V(px . 0)\Vs + FI + NEXT main + FI + "EOF +KTHX + +FOR shiftws LEET s \@ + IF s ~ "^{s!+}" + KTHX s [ @+0 + FI +KTHX s + +FOR parse LEET s \@ + LEET first @mult s + IF @TYPE OF (first . 0) ; "list" + KTHX first + FI + LET s first . 1 + LEET op + LEET second + 10 IF s ~ "^s!*{'+-'}" + LET op "b\V\0" + LET s [= @+0 + LET second @mult s + IF @TYPE OF (second . 0) ; "list" + KTHX second + FI + LET s second . 1 + LET first #<#<op (first . 0) (second . 0)#> s#> + GOFOR 10 + FI +KTHX first + +FOR mult LEET s \@ + LEET first @pow s + IF @TYPE OF (first . 0) ; "list" + KTHX first + FI + LET s first . 1 + LEET op + LEET second + 10 IF s ~ "^s!*{'/%'|*![*!^]}" + LET op "b\V\0" + LET s [= @+0 + LET second @pow s + IF @TYPE OF (second . 0) ; "list" + KTHX second + FI + LET s second . 1 + LET first #<#<op (first . 0) (second . 0)#> s#> + GOFOR 10 + FI +KTHX first + +FOR pow LEET s \@ + LEET first @term s + IF @TYPE OF (first . 0) ; "list" + KTHX first + FI + LET s first . 1 + IF s ~ "^s!*{^!|*!*!}" + LET s [= @+0 + LEET second @pow s + IF @TYPE OF (second . 0) ; "list" + KTHX second + FI + LET s second . 1 + KTHX #<#<"b^" (first . 0) (second . 0)#> s#> + FI +KTHX first + +FOR term LEET s \@ + IF s ~ "^s!*(!{}" + LET s [= @+0 + LEET tmp @parse s + IF @TYPE OF (tmp . 0) ; "list" + KTHX tmp + FI + LET s tmp . 1 + IF s ~ "^s!*)!{}" + LET s [= @+0 + KTHX #<(tmp . 0) s#> + FI + KTHX #<"`)' expected" s#> + FI + IF s ~ "^s!*{d!+(.!d!*)?|.!d!+}" + LET s [= @+0 + KTHX #<#<"n" @NUM \0#> s#> + FI + IF s ~ "^s!*{'+-'|log|exp|a?(sin|cos|tan)}" + LEET op \0 + LET s [= @+0 + LEET tmp @pow s + IF @TYPE OF (tmp . 0) ; "list" + KTHX tmp + FI + KTHX #<#<"u\Vop" (tmp . 0)#> (tmp . 1)#> + FI + IF s ~ "^s!*pi{}" + LET s [= @+0 + KTHX #<#<"n" \PI#> s#> + FI + IF s ~ "^s!*e{}" + LET s [= @+0 + KTHX #<#<"n" \E#> s#> + FI +KTHX #<"invalid value" s#> + +FOR eval LEET e \@ + IF e . 0 : "n" + KTHX e . 1 + FI + IF e . 0 . 0 : "u" + LEET right @eval (e . 1) + LEET op e . 0 [ 1 + IF op : "+" + KTHX right + FI + IF op : "-" + KTHX @NEG right + FI + IF op : "log" + KTHX @LN right + FI + IF op : "exp" + KTHX \E ^ right + FI + IF op : "sin" + KTHX @SIN right + FI + IF op : "cos" + KTHX @COS right + FI + IF op : "tan" + KTHX @TAN right + FI + IF op : "asin" + KTHX @ASIN right + FI + IF op : "acos" + KTHX @ACOS right + FI + IF op : "atan" + KTHX @ATAN right + FI + FI + IF e . 0 . 0 : "b" + LEET left @eval (e . 1) + LEET right @eval (e . 2) + LEET op e . 0 . 1 + IF op : "+" + KTHX left + right + FI + IF op : "-" + KTHX left - right + FI + IF op : "*" + KTHX left * right + FI + IF op : "/" + KTHX left / right + FI + IF op : "%" + KTHX left % right + FI + IF op : "^" + KTHX left ^ right + FI + FI +KTHX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/cat.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,42 @@ +#!../ploki +NEXT main-program + +FOR cat LET line @LEGS \@ + IF line ; "" + WUNT line + NEXT cat + END IF +KTHX + +FOR open + IF \@ : "-" + KTHX \EING + FI +KTHX @LAPERS \@ + +FOR main-program +LET status 0 +IF \ARG < 2 + cat \EING + END status +FI +LET i 0 +FOR arg LET i i+1 +IF i < \ARG + LET fh @open \ARG:i + IF @NOT fh + WUNT (\ARG:0_": "_\ARG:i_": "_\!_"\n") + LET status status+1 + NEXT arg + FI + cat fh + IF fh ! \EING + CLAUDS fh + IF \_ + WUNT (\ARG:0_": "_\ARG:i_": "_\!_"\n") + LET status status+1 + FI + FI + NEXT arg +FI +END status
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/env.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +#!../ploki +"Your home directory is \"\V\ENV"HOME"\"\nYour current working directory is \"\V@ENV"PWD"\"\n"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/fac.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,21 @@ +"calculate the faculty of [1..8]: "ß{ +REM faculty program in false and ploki +REM Lukas Mai, 11.09.2003 +REM} [$1=$[\%1\]?~[$1-f;!*]?]f: ^'0-$$0>~\8>|$ { +LET n @LEGS(\EING) +REM} +"result: "ß{ +IF n < 1 | (n > 8) + REM} ~[\f;!.]?[ + "illegal input"ß{ +ELSE + LET f 1 + FOR loop IF n > 0 + LET f f * n + LET n n - 1 + NEXT loop + FI + WUNT f +FI +REM} ]?" +"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/fact.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,20 @@ +#!../ploki +LET n \ARG:1 +FOR $main$1$loop LET x @kt n +LET n n/x +"\Vx " +IF @NOT(n > 1) + " + END +FI +NEXT $main$1$loop + +FOR kt LEET i 2 +FOR kt$1$loop IF \@ / 2 < i + KTHX \@ +FI +IF \@ % i = 0 + KTHX i +FI +LET i i + 1 +NEXT kt$1$loop
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/facul.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,8 @@ +#!/usr/local/bin/ploki +@x \ARG:1 . 1 _" +END +FOR x IF \@ < 2 + KTHX @OMFG \@ + FI + LEET x \@ +KTHX @OMFG (@x (x - 1) . (x * \@))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/fib.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,13 @@ +#!../ploki +LET n 1 +FOR loop WUNT (@fib(n) _ " ") +LET n n + 1 +IF n > 13 + WUNT "\n" + END +FI +NEXT loop +FOR fib IF \@ > 2 + KTHX @INT(@SQRT 1.25 + .5 * @fib(\@ - 1)) + FI +KTHX 1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/fibcheck.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,14 @@ +#!../ploki +REM fibonacci sequence tester +REM sample input: +REM x x xx xxx xxxxx +REM x x x +FOR line LET line @LEGS \EING + IF line ; "" + IF line ~ "^s!*({[S!|[{S!}|[2!|1![1]?]{0!}[2]?][0]?]}s!+)+$" + "fibonacci sequence! + ELSE + "nope... + FI + NEXT line + FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/foobar.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +#!../ploki +REM should print "foobar" :-) +\Q"foo\c"\V "ar""_"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/goto.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,15 @@ +#!../ploki +WUNT "1..3 +GOTO 0 +01 WUNT "ERROR MESSAGE +10 END +10 WUNT "ERROR MESSAGE +WUNT "ok 1 +0 GOTO 10 +20 WUNT "ok 3 +20 GOTO 20 +20 GOTO 0 +20 WUNT "ERROR MESSAGE +10 WUNT "ok 2 +10 GOTO 20 +00 GOTO 10
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/hanoi.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,25 @@ +#!../ploki +IF \ARG < 2 + WUNT "Usage: \V\ARG:0 NUMBER\n" + END -1 +FI +LET a "a" +LET b "b" +LET c "c" +move \ARG:1 +WUNT "\n" +END +FOR move IF \@ > 0 + LEET ax a + LEET bx b + LEET cx c + LET b cx + LET c bx + move \@ - 1 + WUNT (ax_bx_" ") + LET a cx + LET b bx + LET c ax + move \@ - 1 + FI +KTHX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/hell.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +#!../ploki +"Hello, world!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/hello.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +#!../ploki +10 WUNT \AUSG "Hello, world!\n" +20 END 0
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/insert.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +#!../ploki +INSERT SOME FILE HERE +@foo 2 _ "
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/io.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +#!../ploki +LETs@LEGS(\EING) +WUNTs +IF:s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/list.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,27 @@ +#!../ploki +NEXT main + +FOR join LEET s "" +LEET i 0 +IF i < @LENGTH (\@ . 1) + LET s \@ . 1 . 0 + LET i i+1 + FOR join-loop IF i < @LENGTH (\@ . 1) + LET s s _ (\@ . 0) _ (\@ . 1 . i) + LET i i+1 + NEXT join-loop + FI +FI +KTHX s + +FOR map LEET r #<#> +LEET i 0 +FOR map-loop IF i < @LENGTH (\@ . 1) + LET r r _ #<(\@ . 0 . (\@ . 1 . i))#> + LET i i+1 + NEXT map-loop +FI +KTHX r + +FOR main LET list #<1 -2 3 52#> +@join #<" " @map #<@OMFG(\@ * 2) list#>#> _"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/loop.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +IF
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/mark.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,19 @@ +#!../ploki +FOREACH LET$@LEGS\EING +IF$: +END +FIX +IF;\ARG:1 +LETO +FOR; LETP $[O~\R\ARG:1 +IFP +LET P+O+P +LET$ $]P_"\33[1m\V ($[P]@LENGTH\ARG:1)\033[m"_($[(P+@LENGTH\ARG:1 +LETO7+@LENGTH\ARG:1+P +IF$[O; +NEXT; +FISH +FITS +END IF BEGIN ELSE +$ +NEXTEACH
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/mod.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,10 @@ +#!../ploki +LET i 1 +i_" +LET i += 2 +i_" +LET a -= 4 +a_" +LET *= 3 +LET a a/ 2 +a_"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/num.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,6 @@ +#!../ploki +IF \ARG < 4 + WUNT "Usage: \V\ARG:0 FROM-BASE TO-BASE NUMBER + END 1 +FI +@REVERSE(\ARG:3'\ARG:1`\ARG:2)_"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/omfg.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,8 @@ +#!../ploki +WUNT "2+3\t-3+24\t2+24\t-3+3 +LET a @ADD 2 +LET a$ @ADD @NEG 3 +WUNT \AUSG a.3 _ "\t" _ (a$.24) _"\t "_(a.24)_"\t "_(a$.3)_" +END +FOR ADD LEET X \@ +KTHX @OMFG(X + \@)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/out.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +#!../ploki +WUNT \AUSG "STDOUT +WUNT \FEHL "STDERR
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/perl-util.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,167 @@ +GOTO 666 + +FOR map LEET f \@ . 0 + LEET list \@ . 1 + LEET result #<#> + LEET i 0 + 10 IF i < @LENGTH list + LET result _= f . (list . i) + LET i += 1 + GOFOR 10 + FI +KTHX result + +FOR grep LEET f \@ . 0 + LEET list \@ . 1 + LEET result #<#> + LEET i 0 + 10 IF i < @LENGTH list + IF f . (list . i) + LET result _= #<(list . i)#> + FI + LET i += 1 + GOFOR 10 + FI +KTHX result + +FOR s/// LEET str \@ . 0 + LEET pat \@ . 1 + LEET repl \@ . 2 + LEET ms str ~ pat + IF ms + LEET me \_ + IF @TYPE OF repl : "stuff" + LET repl .= str [ ms ] (me - ms) + FI + LET str str ] ms _ repl _ (str [ me) + FI +KTHX str + +FOR s///g LEET str \@ . 0 + LEET pat \@ . 1 + LEET repl \@ . 2 + LEET new + LEET p 0 + LEET ms + LEET me + 10 LET ms str [ p ~ pat + IF ms + LET me \_ + LET new repl + IF @TYPE OF new : "stuff" + LET new .= str [ p [ ms ] (me - ms) + FI + LET new @STR new + LET str str ] (p + ms) _ new _ (str [ (p + me)) + LET p += ms = me + ms + @LENGTH new + IF @NOT (p > @LENGTH str) + GOFOR 10 + FI + FI +KTHX str + +200 LEET b \@.0 _ @REVERSE (\@.1) + LEET result #<#> + LEET d + LEET i 0 + LEET j @LENGTH b - 1 + 210 IF i < j + LET d cmp.#<(b.i) (b.j)#> + IF d < 0 + LET result _= b [ i ] 1 + LET i += 1 + ELSE + IF d > 0 + LET result _= b [ j ] 1 + LET j -= 1 + ELSE + LET result _= b [ i ] 1 + LET i += 1 + LET result _= b [ j ] 1 + LET j -= 1 + FI + FI + GOFOR 210 + ELSE + IF i = j + LET result _= b [ i ] 1 + FI + FI +KTHX result + +FOR sort LEET cmp \@.0 + LEET list \@.1 + IF @LENGTH list < 2 + KTHX list + FI + LEET mid @INT (@LENGTH list / 2) + ABRUF 200 #<@sort #<cmp (list ] mid)#> @sort #<cmp (list [ mid)#>#> +KTHX \_ + +FOR join LEET sep \@.0 + LEET list \@.1 + LEET result "" + IF @LENGTH list + LET result _= list.0 + LEET i 1 + 10 IF i < @LENGTH list + LET result _= sep + LET result _= list.i + LET i += 1 + GOFOR 10 + FI + FI +KTHX result + +FOR split LEET pat \@.0 + LEET str \@.1 + LEET result #<#> + IF "" ~ pat + LEET i 0 + 10 IF i < @LENGTH str + LET result _= #<(str . i)#> + LET i += 1 + GOFOR 10 + FI + ELSE + LEET p 0 + LEET ms + 20 LET ms str [ p ~ pat + IF ms + LET result _= #<(str [ p ] ms)#> + LET p += \_ + GOFOR 20 + FI + LET result _= #<(str [ p)#> + FI +KTHX result + +FOR dumper LEET x \@ + IF @TYPE OF x : "number" + KTHX x + FI + IF @TYPE OF x : "stream" + KTHX "{IO}" _ x + FI + IF @TYPE OF x : "stuff" + KTHX "{EXPR}?" + FI + IF @TYPE OF x : "nothing" + KTHX "()" + FI + IF @TYPE OF x : "list" + KTHX "#<" _ @join #<" " @map #<@OMFG #<@dumper \@#> x#>#> _ "#>" + FI +KTHX "\"" _ @s///g #<x "'P!\\\"'" @OMFG "\\\V@REVERSE (@ORD \@ ` 8)"#> _"\"" + +FOR x LEET s \@ . 0 + LEET n \@ . 1 + LEET res "" + 10 IF n > 0 + LET res _= s + LET n -= 1 + GOFOR 10 + FI +KTHX res + +666
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/quine.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,14 @@ +#!../ploki +REM My first quine! Lukas Mai, 07.03.2003 +LET b "b" +LET n "n" +LET v "v" +LET bb "\\" +LET nn "\n" +LET vv "\"" +LET bn "#!../ploki" +LET vvv "REM My first quine! Lukas Mai, 07.03.2003" +LET vb "LET " +LET nv " " +LET bnv "WUNT (bn_nn _vvv_nn _vb_b_nv_vv_b_vv_nn _vb_n_nv_vv_n_vv_nn _vb_v_nv_vv_v_vv_nn _vb_b_b_nv_vv_bb_bb_vv_nn _vb_n_n_nv_vv_bb_n_vv_nn _vb_v_v_nv_vv_bb_vv_vv_nn _vb_b_n_nv_vv_bn_vv_nn _vb_v_v_v_nv_vv_vvv_vv_nn _vb_v_b_nv_vv_vb_vv_nn _vb_n_v_nv_vv_nv_vv_nn _vb_b_n_v_nv_vv_bnv_vv_nn _bnv_nn)" +WUNT (bn_nn _vvv_nn _vb_b_nv_vv_b_vv_nn _vb_n_nv_vv_n_vv_nn _vb_v_nv_vv_v_vv_nn _vb_b_b_nv_vv_bb_bb_vv_nn _vb_n_n_nv_vv_bb_n_vv_nn _vb_v_v_nv_vv_bb_vv_vv_nn _vb_b_n_nv_vv_bn_vv_nn _vb_v_v_v_nv_vv_vvv_vv_nn _vb_v_b_nv_vv_vb_vv_nn _vb_n_v_nv_vv_nv_vv_nn _vb_b_n_v_nv_vv_bnv_vv_nn _bnv_nn)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/ref.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,17 @@ +GOTO 496 +FOR *&ref-assign*& LET $(\@ . 0) \@ . 1 +KTHX \@ . 1 +FOR *&ref-call&* LEET id \@ . 0 + LEET arg \@ . 1 + IF \L arg : "set" + LEET ref $$ref$$(id) + KTHX @OMFG @*&ref-assign*& #<ref \@#> + FI +KTHX $($$ref$$(id)) +FOR ref LEET val \@ + LET $$ref$cnt$$ += 1 + LEET ref @OMFG @*&ref-call&* #<$$ref$cnt$$ \@#> + LET $$ref$$($$ref$cnt$$) ref + LET $(ref) \@ +KTHX ref +496 #!
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/regex.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +#!../ploki -dr +LET "dummy" ~ \ARG:1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/reset.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,14 @@ +#!../ploki +IF @NOT ("foo" ~ "{.}0!") | (\0 ; "o") + "error + END -1 +FI +IF "foo" ~ "b" + "error + END -1 +FI +IF @DEF-P \0 + "ARGH: match variable not reset + END -1 +FI +"ok
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/ret.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,56 @@ +#!../ploki +REM regular expression tester +NEXT main: + +FOR trymatch + LEET txt \@ . 0 + LEET pat \@ . 1 + LEET ms txt ~ pat + IF ms + LET me \_ + "matched at pos \Vms [\V(txt ] ms)\033[1m\V(txt [ ms ] (me - ms))\033[m\V(txt [ me ] 255)] + IF @DEF-P \0 + WUNT "\\0<\V@-0, \V@+0>: \V\0 + FI + IF @DEF-P \1 + WUNT "\\1<\V@-1, \V@+1>: \V\1 + FI + IF @DEF-P \2 + WUNT "\\2<\V@-2, \V@+2>: \V\2 + FI + ELSE + WUNT "no match + FI +KTHX + +FOR main: + IF \ARG < 2 + WUNT "Usage: \V\ARG:0 PATTERN [FILE] + END @NEG1 + FI + LET pat \ARG:1 + IF \ARG > 2 + LET fh @LAPERS \ARG:2 + IF @NOT fh + WUNT \AUSG \ARG:0_": "_\ARG:2_": "_\!_" + END @NEG1 + FI + FOR buf LET s fh . 4096 + IF s ; "" +#! "appending [\V@TYPE OFs:\V@LENGTHs]\Vs to \Vtxt + LET txt _= s + NEXT buf + FI +#! "matching /\Vpat/ against \Vtxt + trymatch #<txt pat#> + ELSE + "pattern: /\Vpat/ + FOR line LET line @LEGS \EING + IF line ; "" + IF line [ -1 : " + LET line line ] -1 + FI + trymatch #<line pat#> + NEXT line + FI + FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/rev.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,7 @@ +#!../ploki +FOR line LET line @LEGS \EING +IF line ; "" + LET s s _ line + NEXT line +FI +WUNT @REVERSE s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/revrec.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,7 @@ +#!../ploki +FOR f LEET c @GET \EING + IF c > -1 + f + SET c + FI +KTHX
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/rfc822-fun.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,79 @@ +#!../ploki +REM adaption of Jeffrey Friedl's RFC 822 email regex +REM (taken from _Mastering Regular Expressions_) + +GOTO 1000 + +FOR esc KTHX "\\" +FOR Period KTHX ".!" +FOR OpenBr KTHX "[!" +FOR CloseBr KTHX "]!" +FOR OpenParen KTHX "(!" +FOR CloseParen KTHX ")!" +FOR NonASCII KTHX "\x80-\xff" +FOR ctl KTHX "\000-\037" +FOR CRlist KTHX "\n\015" + +FOR qtext KTHX "'^\V@esc()\V@NonASCII()\V@CRlist()\"'" +FOR dtext KTHX "'^\V@esc()\V@NonASCII()\V@CRlist()[]'" +FOR quoted$pair KTHX @esc() _ "'^\V@NonASCII()'" + +FOR ctext KTHX "'^\V@esc()\V@NonASCII()\V@CRlist())('" + +FOR Cnested KTHX @OpenParen() _ @ctext() _ "*(\V@quoted$pair()\V@ctext()*)*" _ @CloseParen() + +FOR comment KTHX @OpenParen() _ @ctext() _ "*((\V@quoted$pair()|\V@Cnested())\V@ctext()*)*" _ @CloseParen() + +FOR X KTHX "' \t'*(\V@comment()' \t'*)*" + +FOR atom$char KTHX "'^() <>\\@,;:\".\V@esc()[]\V@ctl()\V@NonASCII()'" +FOR atom KTHX "<\V@atom$char()+>" + +FOR quoted$str KTHX "\"\V@qtext()*(\V@quoted$pair()\V@qtext()*)*\"" + +FOR word KTHX "(\V@atom()|\V@quoted$str())" + +FOR domain$ref KTHX @atom() + +FOR domain$lit KTHX @OpenBr() _ "(\V@dtext()|\V@quoted$pair())*" _ @CloseBr() + +FOR sub$domain KTHX "(\V@domain$ref()|\V@domain$lit())" _ @X() + +FOR domain KTHX @sub$domain() _ "(\V@Period()\V@X()\V@sub$domain())*" + +FOR route KTHX "@" _ @X() _ @domain() _ "(,\V@X()\V@domain())*:!" _ @X() + +FOR local$part KTHX @word() _ @X() _ "(\V@Period()\V@X()\V@word()\V@X())*" + +FOR addr$spec KTHX @local$part() _ "@" _ @X() _ @domain() + +FOR route$addr KTHX "<!(\V@route())?\V@addr$spec()>!" + +FOR phrase$ctl KTHX "\000-\010\012-\037" + +FOR phrase$char KTHX "'^()<>@,;:\".\V@esc()[]\V@NonASCII()\V@phrase$ctl()'" + +FOR phrase KTHX @word() _ @phrase$char() _ "*((\V@comment()|\V@quoted$str())\V@phrase$char()*)*" + +FOR mailbox KTHX @X() _ "(\V@addr$spec()|\V@phrase()\V@route$addr())" + + +1000 REM *** main code *** + +REM ****************** +REM ** test snippet ** +REM ****************** + +LET status 0 +LET i 1 +FOR main-loop IF i < \ARG + IF \ARG:i ~ ("^" _ @mailbox() _ "$") + "`\V\ARG:i' is syntactically valid. + ELSE + "`\V\ARG:i' is syntactically invalid. + LET status @NEG 1 + FI + LET i += 1 + NEXT main-loop + FI + END status
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/rfc822.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,75 @@ +#!../ploki +REM adaption of Jeffrey Friedl's RFC 822 email regex +REM (taken from _Mastering Regular Expressions_) + +LET $esc "\\" +LET $Period ".!" +LET $OpenBr "[!" +LET $CloseBr "]!" +LET $OpenParen "(!" +LET $CloseParen ")!" +LET $NonASCII "\x80-\xff" +LET $ctl "\000-\037" +LET $CRlist "\n\015" + +LET $qtext "'^\V$esc\V$NonASCII\V$CRlist\"'" +LET $dtext "'^\V$esc\V$NonASCII\V$CRlist[]'" +LET $quoted$pair $esc _ "'^\V$NonASCII'" + +LET $ctext "'^\V$esc\V$NonASCII\V$CRlist)('" + +LET $Cnested $OpenParen _ $ctext _ "*(\V$quoted$pair\V$ctext*)*" _ $CloseParen + +LET $comment $OpenParen _ $ctext _ "*((\V$quoted$pair|\V$Cnested)\V$ctext*)*" _ $CloseParen + +LET $X "' \t'*(\V$comment' \t'*)*" + +LET $atom$char "'^() <>\\@,;:\".\V$esc[]\V$ctl\V$NonASCII'" +LET $atom "<\V$atom$char+>" + +LET $quoted$str "\"\V$qtext*(\V$quoted$pair\V$qtext*)*\"" + +LET $word "(\V$atom|\V$quoted$str)" + +LET $domain$ref $atom + +LET $domain$lit $OpenBr _ "(\V$dtext|\V$quoted$pair)*" _ $CloseBr + +LET $sub$domain "(\V$domain$ref|\V$domain$lit)" _ $X + +LET $domain $sub$domain _ "(\V$Period\V$X\V$sub$domain)*" + +LET $route "@" _ $X _ $domain _ "(,\V$X\V$domain)*:!" _ $X + +LET $local$part $word _ $X _ "(\V$Period\V$X\V$word\V$X)*" + +LET $addr$spec $local$part _ "@" _ $X _ $domain + +LET $route$addr "<!(\V$route)?\V$addr$spec>!" + +LET $phrase$ctl "\000-\010\012-\037" + +LET $phrase$char "'^()<>@,;:\".\V$esc[]\V$NonASCII\V$phrase$ctl'" + +LET $phrase $word _ $phrase$char _ "*((\V$comment|\V$quoted$str)\V$phrase$char*)*" + +LET $mailbox $X _ "(\V$addr$spec|\V$phrase\V$route$addr)" + + +REM ****************** +REM ** test snippet ** +REM ****************** + +LET status 0 +LET i 1 +FOR main-loop IF i < \ARG + IF \ARG:i ~ ("^" _ $mailbox _ "$") + "`\V\ARG:i' is syntactically valid. + ELSE + "`\V\ARG:i' is syntactically invalid. + LET status @NEG 1 + FI + LET i += 1 + NEXT main-loop + FI + END status
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/string.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,12 @@ +#!../ploki +LET pat "\"{<'^\"\\'*><(\\.<'^\"\\'*>)*>}\"" +FOR line LET line @LEGS \EING +IF line ; "" + FOR match LET p line ~ pat + IF p + WUNT "> `\V\0' + LET line line [ (p + 2 + @LENGTH \0) + NEXT match + FI + NEXT line +FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/subst.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,14 @@ +#!../ploki +INSERT perl-util.pk HERE +NEXT main + +FOR mod "double \V\@ -> \V(\@ * 2) +KTHX \@ * 2 + +FOR main + LET s @LEGS \EING + IF s : "" + END + FI + @s///g #<s ".!?d!+" @OMFG(@mod \@)#> + NEXT main
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/throw.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,12 @@ +#!../ploki +LET a @EVAL @foo 2 +a_priv_" +LET a @EVAL @foo 0 +a_", "_\__priv_" +END +FOR foo LEET priv " ERROR MESSAGE" + IF \@ > 0 + KTHX \@ * 2 + ELSE + IACS "error" + FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/try.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,13 @@ +#!../ploki +LET pat "foo{.*}bar" +LET i 0 +FOR loop IF i < 2 + IF "afoo42bar" ?o~ pat + "match \Vi -- \V\0 + ELSE + "no match \Vi + FI + LET i += 1 + LET pat "{a}" + NEXT loop +FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/uncomment.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,30 @@ +#!../ploki +REM Usage: uncomment.pk [FILE [...]] +REM Opens each FILE in turn, removes C (and C++) comments, and prints +REM the results to stdout. Reads from stdin if FILE is omitted. + +INSERT perl-util.pk HERE +LET status 0 +IF \ARG < 2 + @delcom \EING +ELSE + LET i 1 + FOR main-loop LET fh @APERS #<\ARG:i "R"#> + IF @NOT fh + WUNT \FEHL "\V\ARG:0: \V\ARG:i: \V\! + LET status @NEG 1 + ELSE + @delcom fh + CLAUDS fh + FI + LET i += 1 + IF i < \ARG + NEXT main-loop + FI +FI + +END status + +FOR delcom LEET fh \@ + LEET s fh . @NEG 1 +KTHX @s///g #<s "/((\\|?!?!/)\n!)*(/((\\|?!?!/)\n|'^\n')*|*!'^*'**!+((\\|?!?!/)\n!)*('^/*''^*'**!+((\\|?!?!/)\n!)*)*{/})|{(\"((\\|?!?!/).|'^\"')*\"|'!((\\|?!?!/).|'^'!')*'!|.)'^'!\"/'*}" @OMFG (" " ] @DEF-P \1 _ \0)#>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/var.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +#!../ploki +"> " +LETdesoxyribonukleinsaeure("lysergsäurediethylamid")@LEGS\EING +"you said: "_desoxyribonukleinsaeure("lysergsäurediethylamid")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/examples/write.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,13 @@ +#!../ploki +LET fname "foo.txt" +LET fh @SAPERS fname +IF @NOT @IO-P fh + WUNT "\Vfname: \V\!\n" + END -1 +FI +WUNT fh, (\ENV"USER"_" ("_\ENV"HOME"_") "_\ENV"PWD"_"\n"_\?_"\n") +CLAUDS fh +IF \_ + WUNT "\Vfname: \V\!\n" + END -1 +FI
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/expr.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1080 @@ +#include "config.h" +#include "Str.h" +#include "expr.h" +#include "hang.h" +#include "list.h" +#include "main_io.h" +#include "main_label.h" +#include "main_var.h" +#include "mars.h" +#include "match.h" +#include "op.h" +#include "pp.h" +#include "random.h" +#include "re.h" +#include "run.h" +#include "stack.h" +#include "val.h" +#include "venus.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <setjmp.h> + +#ifdef M_PI + #define MY_PI M_PI +#else + #define MY_PI 3.1415926535897932384626433832795028841971693993751058209749445923 +#endif + +#ifdef M_E + #define MY_E M_E +#else + #define MY_E 2.71828182845904523536028747135266249775724709369995957496696762772 +#endif + +typedef struct val *svalp; +stack_declare(svalp, static) + +static void sv_init(svalp *x) { + *x = v_undef(); +} + +static void sv_end(svalp *x) { + v_delete(*x); +} + +static void sv_copy(svalp *dst, const svalp *src) { + v_set(*dst, *src); +} + +stack_define(svalp, static, sv_init, sv_end, sv_copy) +static stack(svalp) Stack; + +static void con_nop(t_context *c) { + (void)c; +} + +ATTR_NORETURN +static void con_error(const t_context *x, const t_context *y) { + (void)x; + (void)y; + NOTREACHED; +} + +stack_define(t_context, extern, con_nop, con_nop, con_error) +stack(t_context) Context; + +void expr_init(void) { + stack_func(svalp, init)(&Stack); + stack_func(t_context, init)(&Context); +} + +void expr_end(void) { + stack_func(t_context, end)(&Context); + stack_func(svalp, end)(&Stack); +} + +void expr_pp(enum t_binop op, struct val *x, struct val *y) { + switch (op) { + case B_AMPERSAND: pp_and(x, y); return; + case B_ANGLE: pp_lt_n(x, y); return; + case B_BACKSPARK: pp_tobase(x, y); return; + case B_BRACELET: pp_gt(x, y); return; + case B_DOUBLE_OH_SEVEN: pp_mod(x, y); return; + case B_EMBRACE: pp_lt(x, y); return; + case B_FLATWORM: pp_concat(x, y); return; + case B_HALF_MESH: pp_eq_n(x, y); return; + case B_HYBRID: pp_ne(x, y); return; + case B_INTERSECTION: pp_add(x, y); return; + case B_RIGHT_ANGLE: pp_gt_n(x, y); return; + case B_SHARK_FIN: pp_pow(x, y); return; + case B_SLAT: pp_div(x, y); return; + case B_SPARK: pp_frombase(x, y); return; + case B_SPARK_SPOT: pp_ne_n(x, y); return; + case B_SPIKE: pp_or(x, y); return; + case B_SPLAT: pp_mult(x, y); return; + case B_SPOT: pp_read(x, y); return; + case B_SQIGGLE: pp_match(x, y); return; + case B_TAIL: pp_comma(x, y); return; + case B_TWO_SPOT: pp_eq(x, y); return; + case B_U_TURN: pp_shift(x, y); return; + case B_U_TURN_BACK: pp_pop(x, y); return; + case B_WORM: pp_sub(x, y); return; + case B_XMATCH: NOTREACHED; + } +} + +enum t_binop expr_binop(int c) { + switch (c) { + case '!': return B_SPARK_SPOT; + case '%': return B_DOUBLE_OH_SEVEN; + case '&': return B_AMPERSAND; + case '\'': return B_SPARK; + case '*': return B_SPLAT; + case '+': return B_INTERSECTION; + case ',': return B_TAIL; + case '-': return B_WORM; + case '.': return B_SPOT; + case '/': return B_SLAT; + case ':': return B_TWO_SPOT; + case ';': return B_HYBRID; + case '<': return B_ANGLE; + case '=': return B_HALF_MESH; + case '>': return B_RIGHT_ANGLE; + case '[': return B_U_TURN; + case ']': return B_U_TURN_BACK; + case '^': return B_SHARK_FIN; + case '_': return B_FLATWORM; + case '`': return B_BACKSPARK; + case '{': return B_EMBRACE; + case '|': return B_SPIKE; + case '}': return B_BRACELET; + case '~': return B_SQIGGLE; + } + NOTREACHED; +} + +void free_expr(struct expr *x) { + if (!x) { + return; + } + + switch (x->type) { + case literE: + v_end(x->v.val); + xfree(x->v.val); + break; + + case varE: + break; + + case varhashE: + free_expr(x->right); + break; + + case symbolE: + switch (x->op) { + case S_ARGV: + free_expr(x->right); + break; + } + break; + + case unopE: + free_expr(x->right); + if (x->op == F_MATCH) { + re_free(x->left.rx); + } + break; + + case binopE: + free_expr(x->left.expr); + free_expr(x->right); + break; + + case listE: + free_expr(x->right); + free_expr(x->left.expr); + break; + } + xfree(x); +} + +static struct expr *undef(void) { + struct expr *e; + e = xmalloc(1, sizeof *e); + e->type = literE; + e->left.expr = e->right = NULL; + e->v.val = v_undef(); + return e; +} + +static void xv_delete(void *v) { + v_delete(v); +} + +struct expr *get_lval(struct op *op) { + struct expr *x; + int c; + size_t n; + + St_shiftws(&op->txt); + c = ST_FIRSTCHAR(&op->txt); + if (!(c == '$' || isalpha(c))) { + return NULL; + } + for (n = 1; (c = ST_INDEX(&op->txt, n)) == '$' || isalpha(c); ++n) + ; + + x = xmalloc(1, sizeof *x); + x->left.expr = x->right = NULL; + + if (ST_INDEX(&op->txt, n) != '(') { + x->type = varE; + if ((x->v.tent = vr_exists(Var_plain, St_ptr(&op->txt), n)) == VR_NO_COOKIE) { + x->v.tent = vr_register(Var_plain, St_ptr(&op->txt), n, v_undef()); + } + St_del(&op->txt, 0, n); + } else { + x->type = varhashE; + if ((x->v.tent = vr_exists(Var_hash, St_ptr(&op->txt), n)) == VR_NO_COOKIE) { + x->v.tent = vr_register(Var_hash, St_ptr(&op->txt), n, sh_new(xv_delete)); + } + St_del(&op->txt, 0, n + 1); + x->right = get_expr(op); + if (ST_FIRSTCHAR(&op->txt) == ')') { + St_shift(&op->txt); + } + } + return x; +} + +ATTR_CONST +static int xval(int c) { + switch (c) { + case '0': return 0; + case '1': return 1; + case '2': return 2; + case '3': return 3; + case '4': return 4; + case '5': return 5; + case '6': return 6; + case '7': return 7; + case '8': return 8; + case '9': return 9; + case 'A': + case 'a': return 10; + case 'B': + case 'b': return 11; + case 'C': + case 'c': return 12; + case 'D': + case 'd': return 13; + case 'E': + case 'e': return 14; + case 'F': + case 'f': return 15; + } + NOTREACHED; +} + +static struct expr *get_value(struct op *, int); + +static struct expr *get_list(struct op *op, int null) { + struct expr *e; + + e = xmalloc(1, sizeof *e); + e->type = listE; + if ((e->right = get_value(op, 1))) { + e->left.expr = get_list(op, 1); + } else if (null) { + xfree(e); + return NULL; + } else { + e->right = e->left.expr = NULL; + } + return e; +} + +static struct expr *get_value(struct op *op, int null) { + struct expr *e; + int c; + + St_shiftws(&op->txt); + if (!St_len(&op->txt)) { + return null ? NULL : undef(); + } + c = ST_FIRSTCHAR(&op->txt); + + if (c == '$' || isalpha(c)) { + return get_lval(op); + } + + if (isdigit(c) || (c == '.' && isdigit(ST_INDEX(&op->txt, 1)))) { + char *tmp; + + e = undef(); + tmp = St_ptr(&op->txt); + v_set_n(e->v.val, strtod(tmp, &tmp)); + tmp += tmp == St_ptr(&op->txt); + St_del(&op->txt, 0, tmp - St_ptr(&op->txt)); + + return e; + } + + if (OPERATOR_P(c)) { + e = xmalloc(1, sizeof *e); + e->type = binopE; + e->op = expr_binop(c); + St_shift(&op->txt); + e->left.expr = undef(); + e->right = get_value(op, 0); + return e; + } + if (c == '?' && ST_INDEX(&op->txt, 1) == 'o' && ST_INDEX(&op->txt, 2) == '~') { + e = xmalloc(1, sizeof *e); + e->type = binopE; + e->op = B_XMATCH; + St_del(&op->txt, 0, 3); + e->left.expr = undef(); + e->right = get_value(op, 0); + return e; + } + + switch (c) { + case '#': + if (ST_INDEX(&op->txt, 1) != '<') { + goto unrecog; + } + St_del(&op->txt, 0, 2); + e = get_list(op, 0); + St_shiftws(&op->txt); + if (ST_FIRSTCHAR(&op->txt) == '#' && ST_INDEX(&op->txt, 1) == '>') { + St_del(&op->txt, 0, 2); + } + break; + + case '(': + St_shift(&op->txt); + e = get_expr(op); + St_shiftws(&op->txt); + if (ST_FIRSTCHAR(&op->txt) == ')') { + St_shift(&op->txt); + } + break; + + case '"': { + struct val *v; + St_shift(&op->txt); + e = undef(); + v = e->v.val; + V_STR(v); + for (; St_len(&op->txt) && (c = St_shift(&op->txt)) != '"'; ) { + switch (c) { + case '\\': + if (St_len(&op->txt) == 0) { + v_cat_c(v, c); + break; + } + c = St_shift(&op->txt); + if (c >= '0' && c <= '7') { + int oct; + oct = c - '0'; + c = ST_FIRSTCHAR(&op->txt); + if (c >= '0' && c <= '7') { + oct *= 010; + oct += c - '0'; + St_shift(&op->txt); + c = ST_FIRSTCHAR(&op->txt); + if (c >= '0' && c <= '7') { + oct *= 010; + oct += c - '0'; + St_shift(&op->txt); + } + } + v_cat_c(v, oct); + break; + } + switch (c) { + case 'x': + c = ST_FIRSTCHAR(&op->txt); + if (isxdigit(c)) { + int hex; + hex = xval(c); + St_shift(&op->txt); + c = ST_FIRSTCHAR(&op->txt); + if (isxdigit(c)) { + hex *= 0x10; + hex += xval(c); + St_shift(&op->txt); + } + v_cat_c(v, hex); + } else { + v_cat_m(v, "\\x", 2); + } + break; + + case 'a': v_cat_c(v, '\a'); break; + case 'b': v_cat_c(v, '\b'); break; + case 'f': v_cat_c(v, '\f'); break; + case 'n': v_cat_c(v, '\n'); break; + case 'r': v_cat_c(v, '\r'); break; + case 't': v_cat_c(v, '\t'); break; + case 'v': v_cat_c(v, '\v'); break; + + case 'c': + if (St_len(&op->txt)) { + c = St_shift(&op->txt); + v_cat_c(v, (toupper(c) + 64) % 128); + } else { + v_cat_m(v, "\\c", 2); + } + break; + + case 'V': { + struct expr *tmp; + tmp = e; + e = xmalloc(1, sizeof *e); + e->type = binopE; + e->op = B_FLATWORM; + e->left.expr = tmp; + e->right = get_value(op, 0); + tmp = e; + e = xmalloc(1, sizeof *e); + e->type = binopE; + e->op = B_FLATWORM; + e->left.expr = tmp; + e->right = undef(); + v = e->right->v.val; + break; + } + + default: + v_cat_c(v, c); + break; + } + break; + + default: + v_cat_c(v, c); + break; + } + } + } + break; + + case '\\': + St_shift(&op->txt); + e = xmalloc(1, sizeof *e); + e->type = symbolE; + e->right = NULL; + e->left.expr = NULL; + + c = ST_FIRSTCHAR(&op->txt); + if (isdigit(c)) { + char *tmp = St_ptr(&op->txt); + e->left.bonus = strtoul(tmp, &tmp, 10); + St_del(&op->txt, 0, tmp - St_ptr(&op->txt)); + e->op = S_MATCH; + } else switch (c) { + case '!': St_shift(&op->txt); e->op = S_ERR; break; + case '?': St_shift(&op->txt); e->op = S_RAND; break; + case '_': St_shift(&op->txt); e->op = S_RESULT; break; + + case '@': + St_shift(&op->txt); + e->op = S_ARG; + break; + + case 'A': + switch (ST_INDEX(&op->txt, 1)) { + case 'R': + if (ST_INDEX(&op->txt, 2) == 'G') { + St_del(&op->txt, 0, 3); + e->op = S_ARGC; + if (ST_FIRSTCHAR(&op->txt) == ':') { + St_shift(&op->txt); + e->op = S_ARGV; + e->right = get_value(op, 0); + } + break; + } + goto nullsym; + + case 'U': + if (ST_INDEX(&op->txt, 2) == 'S' && + ST_INDEX(&op->txt, 3) == 'G') { + St_del(&op->txt, 0, 4); + e->op = S_STDOUT; + break; + } + goto nullsym; + + default: + goto nullsym; + } + break; + + case 'E': + switch (ST_INDEX(&op->txt, 1)) { + case 'I': + if ( + ST_INDEX(&op->txt, 2) == 'N' && + ST_INDEX(&op->txt, 3) == 'G' + ) { + St_del(&op->txt, 0, 4); + e->op = S_STDIN; + break; + } + if (0) + case 'N': { + if (ST_INDEX(&op->txt, 2) == 'V') { + St_del(&op->txt, 0, 3); + e->type = unopE; + e->op = F_GETENV; + e->right = get_value(op, 0); + break; + } + } + /*DURCHFALL*/ + default: + St_shift(&op->txt); + e->op = S_EULER; + break; + } + break; + + case 'F': + if ( + ST_INDEX(&op->txt, 1) == 'E' && + ST_INDEX(&op->txt, 2) == 'H' && + ST_INDEX(&op->txt, 3) == 'L' + ) { + St_del(&op->txt, 0, 4); + e->op = S_STDERR; + break; + } + goto nullsym; + + case 'L': e->op = F_LOWER; goto simplefunc; + case 'Q': e->op = F_QUOTE; goto simplefunc; + case 'R': e->op = F_RE_ESC; goto simplefunc; + case 'U': e->op = F_UPPER; goto simplefunc; +simplefunc: + St_shift(&op->txt); + e->type = unopE; + e->right = get_value(op, 0); + break; + + case 'P': + if (ST_INDEX(&op->txt, 1) == 'I') { + St_del(&op->txt, 0, 2); + e->op = S_LUDOLF; + break; + } + goto nullsym; + +nullsym: + default: + e->op = S_NUL; + break; + } + break; + + case '@': + #define CASE_DO_STUFF(n, o) \ + if (1) { \ + St_del(&op->txt, 0, (n)); \ + e->op = (o); \ + e->right = get_value(op, 0); \ + break; \ + } else ((void)0) + + #define CASE(i, w, n, o) \ + case i: if (1) { \ + if (St_len(&op->txt) < (n) || St_ncmp_m(&op->txt, w, n)) { \ + goto usrfunc; \ + } \ + CASE_DO_STUFF(n, o); \ + } else ((void)0) + + St_shift(&op->txt); + e = xmalloc(1, sizeof *e); + e->type = unopE; + e->left.expr = NULL; + + switch (ST_FIRSTCHAR(&op->txt)) { + case '+': CASE_DO_STUFF(1, F_MOEND); + case '-': CASE_DO_STUFF(1, F_MOSTART); + case 'A': + switch (ST_INDEX(&op->txt, 1)) { + CASE('B', "ABS", 3, F_ABS); + CASE('C', "ACOS", 4, F_ACOS); + CASE('P', "APERS", 5, F_OPEN); + CASE('S', "ASIN", 4, F_ASIN); + case 'T': + if (St_len(&op->txt) >= 4) { + if (St_ncmp_m(&op->txt, "ATAN2", 5) == 0) { + CASE_DO_STUFF(5, F_ATAN2); + } + if (St_ncmp_m(&op->txt, "ATAN", 4) == 0) { + CASE_DO_STUFF(4, F_ATAN); + } + } + goto usrfunc; + + default: + goto usrfunc; + } + break; + + case 'C': + switch (ST_INDEX(&op->txt, 1)) { + CASE('H', "CHR", 3, F_CHR); + CASE('O', "COS", 3, F_COS); + default: + goto usrfunc; + } + break; + + CASE('D', "DEF-P", 5, F_DEFINED); + + case 'E': + switch (ST_INDEX(&op->txt, 1)) { + CASE('D', "EDD-P", 5, F_EOF); + CASE('N', "ENV", 3, F_GETENV); + CASE('R', "ERR-P", 5, F_ERROR); + CASE('V', "EVAL", 4, F_CATCH); + default: goto usrfunc; + } + break; + + CASE('G', "GET", 3, F_GETC); + + case 'I': + switch (ST_INDEX(&op->txt, 1)) { + CASE('N', "INT", 3, F_INT); + CASE('O', "IO-P", 4, F_IO); + default: goto usrfunc; + } + break; + + case 'L': + switch (ST_INDEX(&op->txt, 1)) { + CASE('A', "LAPERS", 6, F_OPENR); + case 'E': + switch (ST_INDEX(&op->txt, 2)) { + CASE('G', "LEGS", 4, F_GETS); + CASE('N', "LENGTH", 6, F_LENGTH); + default: goto usrfunc; + } + break; + CASE('G', "LG", 2, F_LOG10); + CASE('N', "LN", 2, F_LOG); + default: goto usrfunc; + } + break; + + case 'N': + switch (ST_INDEX(&op->txt, 1)) { + CASE('E', "NEG", 3, F_NEG); + CASE('O', "NOT", 3, F_NOT); + CASE('U', "NUM", 3, F_NUM); + default: goto usrfunc; + } + break; + + case 'O': + switch (ST_INDEX(&op->txt, 1)) { + CASE('R', "ORD", 3, F_ORD); + CASE('M', "OMFG", 4, F_FREEZE); + default: goto usrfunc; + } + break; + + case 'R': + if (ST_INDEX(&op->txt, 1) != 'E') { + goto usrfunc; + } + switch (ST_INDEX(&op->txt, 2)) { + CASE('M', "REMOVE", 6, F_REMOVE); + CASE('N', "RENAEM", 6, F_RENAME); + CASE('V', "REVERSE", 7, F_REVERSE); + default: goto usrfunc; + } + break; + + case 'S': + switch (ST_INDEX(&op->txt, 1)) { + case 'A': + switch (ST_INDEX(&op->txt, 2)) { + CASE('G', "SAG", 3, F_TELL); + CASE('P', "SAPERS", 6, F_OPENW); + default: goto usrfunc; + } + break; + CASE('I', "SIN", 3, F_SIN); + CASE('Q', "SQRT", 4, F_SQRT); + CASE('T', "STR", 3, F_STR); + CASE('U', "SUCH", 4, F_SEEK); + default: goto usrfunc; + } + break; + + case 'T': + switch (ST_INDEX(&op->txt, 1)) { + CASE('A', "TAN", 3, F_TAN); + CASE('Y', "TYPE OF", 7, F_TYPEOF); + default: goto usrfunc; + } + break; + +usrfunc: + default: + if ((e->left.op = ma_find(&Mars, &op->txt))) { + e->op = F_CALL; + } else { + e->op = F_NUL; + e->left.bonus = op->line; + } + e->right = get_value(op, 0); + break; + } + #undef CASE_DO_STUFF + #undef CASE + break; + +unrecog: + default: + if (null) { + e = NULL; + } else { + e = undef(); + } + break; + } + + return e; +} + +struct expr *get_iobj(struct op *op) { + return get_value(op, 0); +} + +struct expr *get_expr(struct op *op) { + struct expr *a, *b; + + a = get_value(op, 0); + + for (St_shiftws(&op->txt); St_len(&op->txt); St_shiftws(&op->txt)) { + struct expr *tmp; + enum t_binop k; + + if (OPERATOR_P(ST_FIRSTCHAR(&op->txt))) { + k = expr_binop(St_shift(&op->txt)); + b = get_value(op, 0); + } else if (St_ncmp_m(&op->txt, "?o~", 3) == 0) { + k = B_XMATCH; + St_del(&op->txt, 0, 3); + b = get_value(op, 0); + } else { + if (!(b = get_value(op, 1))) { + break; + } + k = B_SPOT; + } + + tmp = a; + a = xmalloc(1, sizeof *a); + a->type = binopE; + a->op = k; + a->left.expr = tmp; + a->right = b; + } + + return a; +} + +#define TOS (*stack_func(svalp, at)(&Stack, 0)) + +void eval_push(struct expr *ex) { + const struct expr *const e = ex; + + switch (e->type) { + case literE: + case varE: + stack_func(svalp, push)(&Stack, &e->v.val); + return; + + case varhashE: { + struct val *tmp, *tos; + const char *ptr; + size_t len; + + eval_push(e->right); + tos = TOS; + ptr = v_sptr(tos, &len); + if ((tmp = sh_get(e->v.hash, ptr, len))) { + v_set(tos, tmp); + } else { + v_set_undef(tos); + } + return; + } + + case symbolE: + switch (e->op) { + case S_NUL: + stack_func(svalp, pushnull)(&Stack); + break; + + case S_ARG: { + struct val *const tmp = &Interp.arg; + stack_func(svalp, push)(&Stack, &tmp); + break; + } + + case S_ARGC: + stack_func(svalp, pushnull)(&Stack); + v_set_n(TOS, Interp.a.argc); + break; + + case S_ARGV: { + struct val *tos; + size_t n; + + eval_push(e->right); + tos = TOS; + V_NUM(tos); + n = RINT(tos->num); + + if (n < Interp.a.argc) { + v_set(tos, &Interp.a.argv[n]); + } else { + v_set_undef(tos); + } + break; + } + + case S_ERR: { + struct val *tos; + const char *const tmp = strerror(errno); + stack_func(svalp, pushnull)(&Stack); + tos = TOS; + v_set_m(tos, tmp, strlen(tmp)); + tos->num = errno; + tos->type |= V_NUM_K; + break; + } + + case S_EULER: + stack_func(svalp, pushnull)(&Stack); + v_set_n(TOS, MY_E); + break; + + case S_LUDOLF: + stack_func(svalp, pushnull)(&Stack); + v_set_n(TOS, MY_PI); + break; + + case S_MATCH: + stack_func(svalp, pushnull)(&Stack); + if (e->left.bonus < Interp.match.length) { + v_set(TOS, &Interp.match.matches[e->left.bonus]); + } + break; + + case S_RAND: + stack_func(svalp, pushnull)(&Stack); + v_set_n(TOS, randval()); + break; + + case S_RESULT: { + struct val *const tmp = &Interp.result; + stack_func(svalp, push)(&Stack, &tmp); + break; + } + + case S_STDIN: + stack_func(svalp, pushnull)(&Stack); + v_set_io(TOS, In); + break; + + case S_STDOUT: + stack_func(svalp, pushnull)(&Stack); + v_set_io(TOS, Out); + break; + + case S_STDERR: + stack_func(svalp, pushnull)(&Stack); + v_set_io(TOS, Err); + break; + } + return; + + case unopE: + if (e->op == F_FREEZE) { + struct sub *const tmp = sub_new(e->right); + stack_func(svalp, pushnull)(&Stack); + v_set_sub(TOS, tmp); + sub_decr(tmp); + return; + } + + if (e->op == F_CATCH) { + const size_t stackmark = stack_func(svalp, size)(&Stack); + t_context *tos; + + stack_func(t_context, pushnull)(&Context); + tos = stack_func(t_context, at)(&Context, 0); + if (!setjmp(tos->buf)) { + tos->depth = stack_func(save_pair, size)(&Saved); + eval_push(e->right); + assert(stack_func(svalp, size)(&Stack) - stackmark == 1u); + stack_func(t_context, clear)(&Context, 1); + } else { + tos = stack_func(t_context, at)(&Context, 0); + depth_restore(tos->depth); + stack_func(t_context, clear)(&Context, 1); + assert(stackmark <= stack_func(svalp, size)(&Stack)); + stack_func(svalp, clear)(&Stack, stack_func(svalp, size)(&Stack) - stackmark); + stack_func(svalp, pushnull)(&Stack); + } + return; + } + + eval_push(e->right); + switch (e->op) { + case F_NUL: { + struct op *op; + struct val *const tos = TOS; + + TOLABEL(tos); + if ((op = ve_findnext(&Venus, ko_str(tos->ko), e->left.bonus))) { + struct val *tmp = v_undef(); + v_set(tmp, tos); + tmp = execute(op, tmp); + v_set(TOS, tmp); + v_delete(tmp); + } else { + hang(); + } + break; + } + + case F_CALL: { + struct val *tmp = v_undef(); + v_set(tmp, TOS); + tmp = execute(e->left.op, tmp); + v_set(TOS, tmp); + v_delete(tmp); + break; + } + + case F_MATCH: + do_match(TOS, e->left.rx); + break; + + case F_ABS: pp_abs(TOS); break; + case F_ACOS: pp_acos(TOS); break; + case F_ASIN: pp_asin(TOS); break; + case F_ATAN: pp_atan(TOS); break; + case F_ATAN2: pp_atan2(TOS); break; + case F_CHR: pp_chr(TOS); break; + case F_COS: pp_cos(TOS); break; + case F_DEFINED: pp_defined(TOS); break; + case F_EOF: pp_eof(TOS); break; + case F_ERROR: pp_error(TOS); break; + case F_GETC: pp_getc(TOS); break; + case F_GETENV: pp_getenv(TOS); break; + case F_GETS: pp_gets(TOS); break; + case F_HANG: hang(); break; + case F_INT: pp_int(TOS); break; + case F_IO: pp_io(TOS); break; + case F_LENGTH: pp_length(TOS); break; + case F_LOG: pp_log(TOS); break; + case F_LOG10: pp_log10(TOS); break; + case F_LOWER: pp_lower(TOS); break; + case F_MOEND: pp_moend(TOS); break; + case F_MOSTART: pp_mostart(TOS); break; + case F_NEG: pp_neg(TOS); break; + case F_NOT: pp_not(TOS); break; + case F_NUM: pp_num(TOS); break; + case F_OPEN: pp_open(TOS); break; + case F_OPENR: pp_openr(TOS); break; + case F_OPENW: pp_openw(TOS); break; + case F_ORD: pp_ord(TOS); break; + case F_QUOTE: pp_quote(TOS); break; + case F_RE_ESC: pp_escape(TOS); break; + case F_REMOVE: pp_remove(TOS); break; + case F_RENAME: pp_rename(TOS); break; + case F_REVERSE: pp_reverse(TOS); break; + case F_SEEK: pp_seek(TOS); break; + case F_SIN: pp_sin(TOS); break; + case F_SQRT: pp_sqrt(TOS); break; + case F_STR: pp_str(TOS); break; + case F_TAN: pp_tan(TOS); break; + case F_TELL: pp_tell(TOS); break; + case F_TYPEOF: pp_typeof(TOS); break; + case F_UPPER: pp_upper(TOS); break; + } + return; + + case binopE: + eval_push(e->left.expr); + eval_push(e->right); + + if (e->op != B_XMATCH) { + expr_pp(e->op, *stack_func(svalp, at)(&Stack, 1), TOS); + stack_func(svalp, clear)(&Stack, 1); + } else { + t_regex *rx; + struct val *const tos = TOS; + V_STR(tos); + rx = re_compile(ko_str(tos->ko)); + stack_func(svalp, clear)(&Stack, 1); + free_expr(ex->right); + ex->right = ex->left.expr; + ex->left.rx = rx; + ex->op = F_MATCH; + ex->type = unopE; + + do_match(TOS, rx); + } + return; + + case listE: { + struct val *tos; + + stack_func(svalp, pushnull)(&Stack); + tos = TOS; + tos->magic.list = li_new(); + tos->type = V_LIST_K; + + if (e->right) { + struct val *tmp; + + eval_push(e->right); + tmp = v_undef(); + stack_func(svalp, pop)(&Stack, &tmp); + li_push(tos->magic.list, tmp); + + if (e->left.expr) { + eval_push(e->left.expr); + assert(!!V_LIST_P(TOS)); + li_append((*stack_func(svalp, at)(&Stack, 1))->magic.list, TOS->magic.list); + stack_func(svalp, clear)(&Stack, 1); + } + } + return; + } + } + + NOTREACHED; +} + +void eval_into(struct expr *e, struct val *v) { + DEBUG(const size_t oldsize = stack_func(svalp, size)(&Stack);) + eval_push(e); + assert(stack_func(svalp, size)(&Stack) - oldsize == 1u); + stack_func(svalp, pop)(&Stack, &v); +} + +struct val *eval_pop(void) { + struct val *new = v_undef(); + assert(stack_func(svalp, size)(&Stack) != 0); + stack_func(svalp, pop)(&Stack, &new); + return new; +} + +struct val *eval_expr(struct expr *e) { + eval_push(e); + return eval_pop(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/expr.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +expr.o: expr.c config.h Str.h expr.h op.h IO.h re.h stack.h xmalloc.h \ + strhash.h val.h kork.h list.h sub.h variable.h hang.h main_io.h \ + main_label.h mars.h venus.h hash.h main_var.h match.h pp.h random.h \ + run.h text.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/expr.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,181 @@ +#ifndef EXPR_H_ +#define EXPR_H_ + +#include "config.h" +#include "Str.h" +#include "op.h" +#include "re.h" +#include "stack.h" +#include "strhash.h" +#include "val.h" +#include "variable.h" + +#include <stddef.h> +#include <setjmp.h> + +enum t_expr { + literE, + varE, + varhashE, + symbolE, + unopE, + binopE, + listE +}; + +enum t_func { + F_CALL = -1, + F_NUL, + F_ABS, + F_ACOS, + F_ASIN, + F_ATAN, + F_ATAN2, + F_CATCH, + F_CHR, + F_COS, + F_DEFINED, + F_EOF, + F_ERROR, + F_EXP, + F_FREEZE, + F_GETC, + F_GETENV, + F_GETS, + F_HANG, + F_INT, + F_IO, + F_LENGTH, + F_LOG, + F_LOG10, + F_LOWER, + F_MATCH, + F_MOEND, + F_MOSTART, + F_NEG, + F_NOT, + F_NUM, + F_OPEN, + F_OPENR, + F_OPENW, + F_ORD, + F_QUOTE, + F_RE_ESC, + F_REMOVE, + F_RENAME, + F_REVERSE, + F_SEEK, + F_SIN, + F_SQRT, + F_STR, + F_TAN, + F_TELL, + F_TYPEOF, + F_UPPER +}; + +enum t_symbol { + S_NUL, + S_ARG, + S_ARGC, + S_ARGV, + S_ERR, + S_EULER, + S_LUDOLF, + S_MATCH, + S_RAND, + S_RESULT, + S_STDIN, + S_STDOUT, + S_STDERR +}; + +enum t_binop { + B_AMPERSAND, + B_ANGLE, + B_BACKSPARK, + B_BRACELET, + B_DOUBLE_OH_SEVEN, + B_EMBRACE, + B_FLATWORM, + B_HALF_MESH, + B_HYBRID, + B_INTERSECTION, + B_RIGHT_ANGLE, + B_SHARK_FIN, + B_SLAT, + B_SPARK, + B_SPARK_SPOT, + B_SPIKE, + B_SPLAT, + B_SPOT, + B_SQIGGLE, + B_TAIL, + B_TWO_SPOT, + B_U_TURN, + B_U_TURN_BACK, + B_WORM, + B_XMATCH +}; + +struct expr { + enum t_expr type; + int op; + union { + t_vr_cookie tent; + struct val *val; + t_strhash *hash; + } v; + struct expr *right; + union { + struct expr *expr; + struct op *op; + t_regex *rx; + size_t bonus; + } left; +}; + +void expr_init(void); +void expr_end(void); + +void free_expr(struct expr *); +struct expr *get_expr(struct op *); +struct expr *get_lval(struct op *); +struct expr *get_iobj(struct op *); + +void eval_push(struct expr *); +void eval_into(struct expr *, struct val *); +struct val *eval_pop(void); +struct val *eval_expr(struct expr *); + +ATTR_PURE +enum t_binop expr_binop(int); + +void expr_pp(enum t_binop, struct val *, struct val *); + +typedef struct { + jmp_buf buf; + size_t depth; +} t_context; + +stack_declare(t_context, extern) +extern stack(t_context) Context; + +#define OPERATORS "_+-*/%^[]<>=!{}:;&|~`'.," +#define OPERATOR_P(c) strchr(OPERATORS, c) + +#define TOLABEL(v) \ +do { \ + V_NUM(v); \ + V_xxx_OFF(v); \ + (v)->num = floor((v)->num + .5); \ + (v)->type = V_NUM_K; \ + v_ok_str(v); \ + ko_grep(v->ko, isdigit); \ + while (ko_at(v->ko, 0) == '0') { \ + ko_shift(v->ko, 1); \ + } \ + (v)->type = V_STR_K; \ +} while (0) + +#endif /* EXPR_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/hang.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,12 @@ +#include "config.h" +#include "hang.h" + +#if HAVE_SLEEP_P + #include SLEEP_HEADER +#endif + +void hang(void) { + for (;;) { + DO_SLEEP; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/hang.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +hang.o: hang.c config.h hang.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/hang.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,9 @@ +#ifndef HANG_H_ +#define HANG_H_ + +#include "config.h" + +ATTR_NORETURN +void hang(void); + +#endif /* HANG_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/hash.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,273 @@ +#include "config.h" +#include "hash.h" +#include "main.h" +#include "main_opt.h" +#include "random.h" +#include "xmalloc.h" + +#include <errno.h> +#include <stddef.h> +#include <stdio.h> +#include <assert.h> + +struct h_entry { + size_t hash; + void *key; + void *value; +}; + +struct h_node { + struct h_entry entry; + struct h_node *next; +}; + +enum {MAGIC = 112}; + +void h_init( + Hash *h, + size_t (*hash)(const void *, size_t), + int (*cmp)(const void *, const void *), + void (*delk)(void *), + void (*delv)(void *) + ) { + size_t i; + + h->entries = 0; + h->brk = -1; + h->iter = -1; + h->iterptr = NULL; + h->seed = randval() * (size_t)-1; + h->delk = delk; + h->delv = delv; + assert(hash != NULL); + h->hash = hash; + assert(cmp != NULL); + h->cmp = cmp; + h->table = xmalloc(h->newsize = h->size = MAGIC, sizeof *h->table); + for (i = 0; i < h->size; ++i) { + h->table[i] = NULL; + } +} + +#define DELKV(p) \ +do { \ + if (h->delk) { \ + h->delk((p)->entry.key); \ + } \ + if (h->delv) { \ + h->delv((p)->entry.value); \ + } \ +} while (0) + +void h_end(Hash *h) { + size_t size, b; + + if (!h->table) + return; + + for (b = 0, size = h->newsize; h->newsize; h->newsize--) { + struct h_node *p; + + if ((p = h->table[h->newsize - 1])) { + ++b; + for (; p; p = h->table[h->newsize - 1]) { + h->table[h->newsize - 1] = p->next; + DELKV(p); + xfree(p); + } + } + } + xfree(h->table); + h->table = NULL; + + if (Opt.debug & DBG_HASH) { + fprintf(stderr, "%s: hash[%lu/%lu/%lu]\n", Prog, (unsigned long)h->entries, (unsigned long)b, (unsigned long)size); + } +} + +ATTR_PURE +static size_t xclip(const Hash *h, const size_t hash_unc) { + size_t hash; + + hash = hash_unc % h->size; + if (hash > h->brk) { + hash = hash_unc % h->newsize; + } + + return hash; +} + +#if 0 +ATTR_PURE +static size_t xhash(const Hash *h, const void *key) { + return xclip(h, h->hash(key, h->seed)); +} +#endif + +#define XRESIZN(h) ((h)->brk + 1u) +#define XSTEP(h) do { if (XRESIZN(h)) xstep(h); } while (0) + +static void xstep(Hash *h) { + struct h_node *rev = NULL; + struct h_node *p; + struct h_node *tmp; + + assert(h->table != NULL); + + for (p = h->table[h->brk]; p; p = tmp) { + tmp = p->next; + p->next = rev; + rev = p; + } + h->table[h->brk--] = NULL; + + if (!XRESIZN(h)) { + h->size = h->newsize; + } + + for (p = rev; p; p = tmp) { + const size_t i = xclip(h, p->entry.hash); + tmp = p->next; + p->next = h->table[i]; + h->table[i] = p; + } +} + +static void xincentries(Hash *h) { + h->entries++; + if (!(XRESIZN(h)) && h->entries / h->size > 3u) { + size_t i; + h->table = xrealloc(h->table, h->newsize = h->size * 2u + 1u); + for (i = h->size; i < h->newsize; ++i) { + h->table[i] = NULL; + } + h->brk = h->size - 1u; + xstep(h); + } +} + +int h_get(Hash *h, const void *key, void **res) { + XSTEP(h); + { + const size_t hash_unc = h->hash(key, h->seed); + const size_t hash = xclip(h, hash_unc); + struct h_node *p; + + for (p = h->table[hash]; p; p = p->next) { + if (hash_unc == p->entry.hash && h->cmp(p->entry.key, key) == 0) { + if (res) { + *res = p->entry.value; + } + return H_OK; + } + } + } + return H_NOENT; +} + +int h_del(Hash *h, const void *key) { + XSTEP(h); + { + const size_t hash_unc = h->hash(key, h->seed); + const size_t hash = xclip(h, hash_unc); + struct h_node **p; + + for (p = &h->table[hash]; *p; p = &(*p)->next) { + if (hash_unc == (*p)->entry.hash && h->cmp((*p)->entry.key, key) == 0) { + struct h_node *tmp = *p; + *p = (*p)->next; + DELKV(tmp); + xfree(tmp); + h->entries--; + return H_OK; + } + } + } + + return H_NOENT; +} + +#if 0 +void h_push(Hash *h, void *key, void *val) { + XSTEP(h); + { + const size_t hash_unc = h->hash(key, h->seed); + const size_t hash = xclip(h, hash_unc); + struct h_node *p; + + p = xmalloc(1, sizeof *p); + p->entry.hash = hash_unc; + p->entry.key = key; + p->entry.value = val; + p->next = h->table[hash]; + h->table[hash] = p; + + xincentries(h); + } +} +#endif + +int h_put(Hash *h, void *key, void *val, int replace) { + XSTEP(h); + { + const size_t hash_unc = h->hash(key, h->seed); + const size_t hash = xclip(h, hash_unc); + struct h_node **p; + + for (p = &h->table[hash]; *p; p = &(*p)->next) { + if (hash_unc == (*p)->entry.hash && h->cmp((*p)->entry.key, key) == 0) { + if (replace) { + DELKV(*p); + (*p)->entry.key = key; + (*p)->entry.value = val; + return H_OK; + } else { + return H_EXIST; + } + } + } + + *p = xmalloc(1, sizeof **p); + + (*p)->entry.hash = hash_unc; + (*p)->entry.key = key; + (*p)->entry.value = val; + (*p)->next = NULL; + + xincentries(h); + } + + return H_OK; +} + +void h_reset(Hash *h) { + h->iter = -1; + h->iterptr = NULL; +} + +int h_nextkv(Hash *h, void **k, void **v) { + if (h->iterptr) { + *k = h->iterptr->entry.key; + *v = h->iterptr->entry.value; + h->iterptr = h->iterptr->next; + return H_OK; + } + + for (h->iter++; h->iter < h->newsize; h->iter++) { + if ((h->iterptr = h->table[h->iter])) { + *k = h->iterptr->entry.key; + *v = h->iterptr->entry.value; + h->iterptr = h->iterptr->next; + return H_OK; + } + } + + h->iter = -1; + return H_NOENT; +} + +#if 0 +size_t (h_entries)(const Hash *h) { + return h_entries(h); +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/hash.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +hash.o: hash.c config.h hash.h main.h main_opt.h random.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/hash.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,47 @@ +#ifndef HASH_H_ +#define HASH_H_ + +#include <stddef.h> + +typedef struct { + size_t entries, size, newsize; + size_t brk; + size_t seed; + size_t iter; + struct h_node *iterptr; + struct h_node **table; + size_t (*hash)(const void *, size_t); + int (*cmp)(const void *, const void *); + void (*delk)(void *); + void (*delv)(void *); +} Hash; + +enum { + H_OK, + H_EXIST, + H_NOENT +}; + +void h_init( + Hash *, + size_t (*)(const void *, size_t), + int (*)(const void *, const void *), + void (*)(void *), + void (*)(void *) + ); +void h_end(Hash *); +int h_get(Hash *, const void *, void **); +int h_del(Hash *, const void *); +#if 0 +void h_push(Hash *, void *, void *); +#endif +int h_put(Hash *, void *, void *, int); +void h_reset(Hash *); +int h_nextkv(Hash *, void **, void **); + +#if 0 +size_t h_entries(const Hash *); +#define h_entries(h) ((h)->entries + 0) +#endif + +#endif /* HASH_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/inc.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +#include "config.h" +#include "inc.h" + +const char *inc_ludes[] = INC_PREFIX_LIST;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/inc.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +inc.o: inc.c config.h inc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/inc.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,6 @@ +#ifndef INC_H_ +#define INC_H_ + +extern const char *inc_ludes[]; + +#endif /* INC_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/indent/ploki.vim Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,43 @@ +" Only load this one if no other indent file was loaded. +if exists("b:did_indent") + finish +endif + +let b:did_indent = 1 +setlocal indentexpr=GetPlokiIndent() +setlocal indentkeys=!^F,o,O,0=ELSE,0=END\ IF,0=FI,0=KTHX + +" Only define the function once. +if exists("*GetPlokiIndent") + finish +endif + +function GetPlokiIndent() + if v:lnum == 1 + return 0 + endif + + let plnum = v:lnum - 1 + let prevline = getline(plnum) + while plnum > 0 && prevline =~ '^\s*$' + let plnum = plnum - 1 + let prevline = getline(plnum) + endwhile + + let ind = indent(plnum) + let thisline = getline(v:lnum) + + if prevline =~ '^FOR\%(\s*\S\+\)\@>\%(\s*KTHX\)\@!' + let ind = ind + &sw + endif + if prevline =~ '^\s*\%(FOR\s*\S\+\|\d*\)\s*\%(IF\|ELSE\)' + let ind = ind + &sw + endif + if thisline =~ '^\s*\%(FOR\s*\S\+\|\d*\)\s*\%(ELSE\|END IF\|FI\)' + let ind = ind - &sw + elseif ind == &sw && thisline =~ '^\s*\%(\d\+\s*\)\=KTHX' + let ind = ind - &sw + endif + + return ind +endfunction
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/kork.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,237 @@ +#include "config.h" +#include "IO.h" +#include "Str.h" +#include "kork.h" +#include "strutil.h" +#include "xmalloc.h" + +#include <stdio.h> +#include <assert.h> +#include <string.h> +#include <ctype.h> + +typedef struct ko_dolphin dolphin; +typedef struct kork kork; + +static dolphin nil = { + { "FLIPPER", 1, 1, 0 }, + 0 +}; + +static dolphin *incr(dolphin *dp) { + ++dp->refs; + return dp; +} + +static void decr(dolphin *dp) { + if (dp->refs) { + --dp->refs; + return; + } + + St_clear(&dp->str); + xfree(dp); +} + +kork *ko_new(void) { + kork *const k = xmalloc(1, sizeof *k); + k->kdp = incr(&nil); + k->offset = 0; + k->length = 0; + return k; +} + +kork *ko_dup(const kork *old) { + kork *const k = xmalloc(1, sizeof *k); + *k = *old; + incr(k->kdp); + return k; +} + +void ko_decouple(kork *k) { + dolphin *const dp = k->kdp; + if (!k->kdp->refs) { + return; + } + k->kdp = xmalloc(1, sizeof *k->kdp); + St_init(&k->kdp->str); + St_cpy_m(&k->kdp->str, St_ptr(&dp->str) + k->offset, k->length); + k->kdp->refs = 0; + k->offset = 0; + decr(dp); +} + +void ko_delete(kork *k) { + decr(k->kdp); + xfree(k); +} + +size_t (ko_length)(const kork *k) { + return ko_length(k); +} + +int ko_at(const kork *k, size_t i) { + return i < k->length ? ST_INDEX(&k->kdp->str, k->offset + i) : EOF; +} + +int ko_lastchar(const kork *k) { + return k->length ? ST_INDEX(&k->kdp->str, k->offset + k->length - 1u) : EOF; +} + +int ko_cmp(const kork *k1, const kork *k2) { + return u_cmp( + St_ptr(&k1->kdp->str) + k1->offset, k1->length, + St_ptr(&k2->kdp->str) + k2->offset, k2->length + ); +} + +void (ko_zero)(kork *k) { + ko_zero(k); +} + +const char *ko_ptr(const kork *k) { + return St_ptr(&k->kdp->str) + k->offset; +} + +static void offoff(kork *k) { + ko_decouple(k); + if (k->offset) { + St_del(&k->kdp->str, 0, k->offset); + k->offset = 0; + } + assert(St_len(&k->kdp->str) >= k->length); +} + +const String *ko_str(kork *k) { + offoff(k); + St_trunc(&k->kdp->str, k->length); + return &k->kdp->str; +} + +const char *ko_szp(kork *k) { + if (k->kdp->refs && k->offset + k->length != St_len(&k->kdp->str)) { + offoff(k); + } + return St_ptr(&k->kdp->str) + k->offset; +} + +void ko_grep(kork *k, int (*pred)(int)) { + offoff(k); + St_grep(&k->kdp->str, pred); + k->length = St_len(&k->kdp->str); +} + +void ko_shift(kork *k, size_t n) { + if (n > k->length) { + n = k->length; + } + k->offset += n; + k->length -= n; +} + +void ko_num(kork *k, double d) { + offoff(k); + St_num(&k->kdp->str, d); + k->length = St_len(&k->kdp->str); +} + +void ko_cpy_m(kork *k, const void *p, size_t n) { + if (!n) { + ko_zero(k); + return; + } + offoff(k); + St_cpy_m(&k->kdp->str, p, n); + k->length = St_len(&k->kdp->str); +} + +void ko_cpy(kork *k, const kork *z) { + ko_cpy_m(k, ko_ptr(z), ko_length(z)); +} + +void ko_cpy_s(kork *k, const char *s) { + ko_cpy_m(k, s, strlen(s)); +} + +void ko_cpy_c(kork *k, char c) { + offoff(k); + St_cpy_c(&k->kdp->str, c); + k->length = 1; +} + +void ko_cat_m(kork *k, const void *p, size_t n) { + if (!n) { + return; + } + if (k->kdp->refs && k->offset + k->length != St_len(&k->kdp->str)) { + offoff(k); + } + assert(k->offset + k->length <= St_len(&k->kdp->str)); + St_trunc(&k->kdp->str, k->offset + k->length); + St_cat_m(&k->kdp->str, p, n); + k->length += n; +} + +void ko_cat(kork *k, const kork *z) { + ko_cat_m(k, ko_ptr(z), ko_length(z)); +} + +void ko_cat_c(kork *k, char c) { + ko_cat_m(k, &c, 1); +} + +void ko_reverse(kork *k) { + offoff(k); + St_reverse(&k->kdp->str); +} + +size_t ko_getline(IO *io, kork *k) { + size_t tmp; + offoff(k); + tmp = io_getline(io, &k->kdp->str); + k->length = St_len(&k->kdp->str); + return tmp; +} + +size_t ko_read(IO *io, kork *k, size_t n) { + size_t tmp; + offoff(k); + tmp = io_read(io, &k->kdp->str, n); + k->length = St_len(&k->kdp->str); + return tmp; +} + +void ko_lower(kork *k) { + offoff(k); + St_lower(&k->kdp->str); +} + +void ko_upper(kork *k) { + offoff(k); + St_upper(&k->kdp->str); +} + +size_t ko_chr(const kork *k, int c) { + const char *const p = memchr(St_ptr(&k->kdp->str) + k->offset, c, k->length); + if (!p) { + return -1; + } + return p - (St_ptr(&k->kdp->str) + k->offset); +} + +void ko_shiftws(kork *k) { + while ( + k->length && + isspace((unsigned char)St_ptr(&k->kdp->str)[k->offset]) + ) { + ++k->offset; + --k->length; + } +} + +void ko_trunc(kork *k, size_t n) { + if (n >= k->length) { + return; + } + k->length = n; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/kork.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +kork.o: kork.c config.h IO.h Str.h kork.h strutil.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/kork.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,63 @@ +#ifndef KORK_H_ +#define KORK_H_ + +#include "config.h" +#include "IO.h" +#include "Str.h" + +#include <stddef.h> + +struct ko_dolphin { + String str; + size_t refs; +}; + +struct kork { + struct ko_dolphin *kdp; + size_t offset, length; +}; + +struct kork *ko_new(void); +struct kork *ko_dup(const struct kork *); +void ko_decouple(struct kork *); +void ko_delete(struct kork *); + +ATTR_PURE +size_t ko_length(const struct kork *); +ATTR_PURE +int ko_at(const struct kork *, size_t); +ATTR_PURE +int ko_lastchar(const struct kork *); +ATTR_PURE +int ko_cmp(const struct kork *, const struct kork *); + +void ko_zero(struct kork *); + +ATTR_PURE +const char *ko_ptr(const struct kork *); +const String *ko_str(struct kork *); +const char *ko_szp(struct kork *); +void ko_grep(struct kork *, int (*)(int)); +void ko_shift(struct kork *, size_t); +void ko_num(struct kork *k, double); +void ko_cpy_m(struct kork *, const void *, size_t); +void ko_cpy(struct kork *, const struct kork *); +void ko_cpy_s(struct kork *, const char *); +void ko_cpy_c(struct kork *, char); +void ko_cat_m(struct kork *, const void *, size_t); +void ko_cat(struct kork *, const struct kork *); +void ko_cat_c(struct kork *, char); +void ko_reverse(struct kork *); +size_t ko_getline(IO *, struct kork *); +size_t ko_read(IO *, struct kork *, size_t); +void ko_lower(struct kork *); +void ko_upper(struct kork *); +ATTR_PURE +size_t ko_chr(const struct kork *, int); +void ko_shiftws(struct kork *); +void ko_trunc(struct kork *, size_t); + +#define ko_length(k) ((k)->length + 0u) +#define ko_zero(k) ((void)((k)->length = 0u)) + +#endif /* KORK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/list.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,219 @@ +#include "list.h" +#include "val.h" +#include "xmalloc.h" + +#include <string.h> +#include <assert.h> + +typedef struct li_whale whale; + +static whale *incr(whale *wp) { + assert(wp->refs > 0); + ++wp->refs; + return wp; +} + +static void decr(whale *wp) { + assert(wp->refs > 0); + if (!--wp->refs) { + while (wp->length) { + --wp->length; + v_delete(wp->field[wp->length]); + } + xfree(wp->field); + xfree(wp); + } +} + +enum {MAGIC = 7}; + +struct list *li_new(void) { + struct list *l = xmalloc(1, sizeof *l); + l->lwp = xmalloc(1, sizeof *l->lwp); + l->lwp->field = xmalloc(l->lwp->size = MAGIC, sizeof *l->lwp->field); + l->lwp->length = 0; + l->lwp->refs = 1; + l->offset = 0; + l->length = 0; + return l; +} + +struct list *li_dup(const struct list *k) { + struct list *l = xmalloc(1, sizeof *l); + l->lwp = incr(k->lwp); + l->offset = k->offset; + l->length = k->length; + return l; +} + +static void decouple(struct list *l, size_t slack) { + size_t i, n; + whale *const wp = l->lwp; + struct val **const field = wp->field + l->offset, **nfield; + assert(wp->refs > 0); + if (wp->refs == 1) { + return; + } + l->lwp = xmalloc(1, sizeof *l->lwp); + n = l->length; + l->lwp->field = nfield = xmalloc(l->lwp->size = n + slack > MAGIC ? n + slack : MAGIC, sizeof *l->lwp->field); + for (i = 0; i < n; ++i) { + v_set(nfield[i] = v_undef(), field[i]); + } + l->lwp->length = n; + l->lwp->refs = 1; + l->offset = 0; + decr(wp); +} + +void li_decouple(struct list *l) { + decouple(l, 1); +} + +void li_delete(struct list *l) { + decr(l->lwp); + xfree(l); +} + +size_t (li_length)(const struct list *l) { + return li_length(l); +} + +struct val *li_at(const struct list *l, size_t i) { + return i < l->length ? l->lwp->field[l->offset + i] : NULL; +} + +int li_cmp(const struct list *k, const struct list *l) { + const size_t len_k = li_length(k), len_l = li_length(l); + struct val **const field_k = k->lwp->field + k->offset, **const field_l = l->lwp->field + l->offset; + size_t i; + + for (i = 0; i < len_k && i < len_l; ++i) { + const int tmp = v_cmp_ls(field_k[i], field_l[i]); + if (tmp) { + return tmp; + } + } + if (i < len_k) { + return 1; + } + if (i < len_l) { + return -1; + } + return 0; +} + +void (li_zero)(struct list *l) { + li_zero(l); +} + +static void vpswap(struct val **p, struct val **q) { + struct val *tmp = *p; + *p = *q; + *q = tmp; +} + +void li_push(struct list *l, struct val *v) { + struct li_whale *wp = l->lwp; + const size_t off = l->offset, len = l->length, wlen = wp->length, wsiz = wp->size; + struct val **field = wp->field; + assert(wp->refs > 0); + if (wp->refs > 1) { + decouple(l, 1); + wp = l->lwp; + field = wp->field; + } else if (off + len < wlen) { + v_delete(field[off + len]); + } else if (wlen < wsiz) { + /* */ + } else if (off) { + size_t i; + for (i = 0; i < len; ++i) { + vpswap(&field[i], &field[off + i]); + } + l->offset = 0; + v_delete(field[len]); + } else { + wp->field = field = xrealloc(field, wp->size *= 2); + } + field[l->offset + l->length++] = v; + if (l->offset + l->length > wlen) { + wp->length = l->offset + l->length; + } +} + +void li_push_cpy(struct list *l, const struct val *v) { + struct li_whale *wp = l->lwp; + const size_t off = l->offset, len = l->length, wlen = wp->length, wsiz = wp->size; + struct val **field = wp->field; + assert(wp->refs > 0); + if (wp->refs > 1) { + decouple(l, 1); + wp = l->lwp; + field = wp->field; + field[l->offset + len] = v_undef(); + } else if (off + len < wlen) { + /* */ + } else if (wlen < wsiz) { + field[off + len] = v_undef(); + } else if (off) { + size_t i; + for (i = 0; i < len; ++i) { + vpswap(&field[i], &field[off + i]); + } + l->offset = 0; + } else { + wp->field = field = xrealloc(field, wp->size *= 2); + field[len] = v_undef(); + } + v_set(field[l->offset + l->length++], v); + if (l->offset + l->length > wlen) { + wp->length = l->offset + l->length; + } +} + +void li_append(struct list *k, const struct list *l) { + struct val **const field = l->lwp->field + l->offset; + const size_t len = li_length(l); + size_t i; + + for (i = 0; i < len; ++i) { + li_push_cpy(k, field[i]); + } +} + +void li_reverse(struct list *l) { + struct val **field; + size_t i, len; + + len = li_length(l); + if (len < 2) { + return; + } + + li_decouple(l); + + field = l->lwp->field + l->offset; + + for (i = 0; i < len / 2; ++i) { + vpswap(&field[i], &field[len - i - 1]); + } +} + +void li_trunc(struct list *l, size_t n) { + if (l->length > n) { + if (!(l->length = n)) { + l->offset = 0; + } + } +} + +void li_shift(struct list *l, size_t n) { + if (n >= li_length(l)) { + li_zero(l); + return; + } + + l->offset += n; + l->length -= n; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/list.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +list.o: list.c list.h config.h val.h IO.h Str.h kork.h sub.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/list.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,42 @@ +#ifndef LIST_H_ +#define LIST_H_ + +#include "config.h" + +#include <stddef.h> + +struct li_whale { + struct val **field; + size_t length, size; + size_t refs; +}; + +struct list { + struct li_whale *lwp; + size_t offset, length; +}; + +struct list *li_new(void); +struct list *li_dup(const struct list *); +void li_decouple(struct list *); +void li_delete(struct list *); + +ATTR_PURE +size_t li_length(const struct list *); +ATTR_PURE +struct val *li_at(const struct list *, size_t); +ATTR_PURE +int li_cmp(const struct list *, const struct list *); + +void li_zero(struct list *); +void li_push(struct list *, struct val *); +void li_push_cpy(struct list *, const struct val *); +void li_append(struct list *, const struct list *); +void li_reverse(struct list *); +void li_trunc(struct list *, size_t); +void li_shift(struct list *, size_t); + +#define li_length(l) ((l)->length + 0) +#define li_zero(l) ((void)(l->offset = l->length = 0)) + +#endif /* LIST_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,307 @@ +#include "IO.h" +#include "Str.h" +#include "atechit.h" +#include "compile.h" +#include "deparse.h" +#include "expr.h" +#include "inc.h" +#include "main.h" +#include "main_io.h" +#include "main_label.h" +#include "main_opt.h" +#include "main_var.h" +#include "mars.h" +#include "opt.h" +#include "parse.h" +#include "random.h" +#include "re.h" +#include "run.h" +#include "text.h" +#include "transmogrify.h" +#include "val.h" +#include "venus.h" +#include "version.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#define NAME "ploki" +#define WARN(x) fprintf(stderr, "%s: %s: %s\n", Prog, x, strerror(errno)) + +const char *Prog = NAME; +IO *In, *Out, *Err; +struct venus Venus; +struct mars Mars; +struct Options Opt; +t_vr_container *Var_plain, *Var_hash; + +static int my_mars_end_flag; +static void my_mars_end(void) { + if (!my_mars_end_flag) { + ma_end(&Mars); + } +} + +static void my_venus_end(void) { + ve_end(&Venus); +} + +static struct text text; +static void my_text_off(void) { + text_off(&text); +} + +static void xv_delete(void *v) { + v_delete(v); +} + +static void xsh_delete(void *sh) { + sh_delete(sh); +} + +static void var_end(void) { + if (Var_plain) { + vr_delete(Var_plain); + Var_plain = 0; + } + if (Var_hash) { + vr_delete(Var_hash); + Var_hash = 0; + } +} + +static char *s_lastof(const char *s, const char *set) { + const char *t = s + strlen(s); + while (t > s) { + --t; + if (strchr(set, *t)) { + return (char *)t; /* const correctness is for C++ programmers! */ + } + } + return NULL; +} + +static void usage(void) { + printf( + "Usage: %s [OPTIONS] [FILE [ARG]...]\n" + "\n" + "Available options:\n" + "\n" + " -h print a short help message and exit\n" + " -v print version and configuration info and exit\n" + " -MO=Deparse turn the compiled program back into ploki source\n" + " -O disable any optimizations\n" + " -d FLAGS print debugging info\n" + " FLAGS must be one or more of the following:\n" + " h hash tables\n" + " o opcode execution\n" + " r regex engine\n" + "\n" + "%s" + , Prog, + "Interpret FILE as ploki program and execute it, unless -MO=Deparse is\n" + "specified. With no FILE, or when FILE is -, read from standard input.\n" + "Any ARGs are passed through to the program.\n" + ); +} + +static void printinc(void) { + size_t i; + for (i = 0; inc_ludes[i]; ++i) { + printf(" \"%s\"", inc_ludes[i]); + } +} + +int main(int argc, char **argv) { + IO *f; + int c; + + if (argc > 0 && argv[0][0]) { + Prog = argv[0]; + } + + while ((c = opt_get(argc, argv, "-:?M:Od:hv")) != -1) { + switch (c) { +invalid_option: + fprintf(stderr, "%s: invalid option `%c'\n", Prog, c); + return EXIT_FAILURE; + + /* option aliasing */ + case '-': + if (!opt_arg) { + goto invalid_option; + } + if (!strncmp("help", opt_arg, strlen(opt_arg))) { + case 'h': + case '?': + usage(); + return EXIT_SUCCESS; + } + if (!strncmp("version", opt_arg, strlen(opt_arg))) { + case 'v': + printf( + "This is %s v%s\n" + "%cvsnprintf %csleep %c/dev/urandom %s%s %cM_PI %cM_E\nINC contains:", + NAME, + Version, + HAVE_VSNPRINTF_P ? '+' : '-', + HAVE_SLEEP_P ? '+' : '-', + HAVE_DEV_URANDOM_P ? '+' : '-', + DIR_END ? "+DIRSEP:" : "-DIRSEP", + DIR_END ? DIR_END : "", + #ifdef M_PI + '+' + #else + '-' + #endif + , + #ifdef M_E + '+' + #else + '-' + #endif + ); + printinc(); + fputs("\nWritten by Lukas Mai\n", stdout); + return EXIT_SUCCESS; + } + fprintf(stderr, "%s: invalid option `%s'\n", Prog, opt_arg); + return EXIT_FAILURE; + + case 'd': + if (!opt_arg || !opt_arg[0]) { + fprintf(stderr, "%s: option `%c' requires an argument\n", Prog, c); + return EXIT_FAILURE; + } else { + const char *a = opt_arg; + for (; *a; ++a) { + switch (*a) { + case 'h': Opt.debug |= DBG_HASH; break; + case 'o': Opt.debug |= DBG_OPS; break; + case 'r': Opt.debug |= DBG_REGEX; break; + default: + fprintf(stderr, "%s: option d's argument must be one of [hor], not `%s'\n", Prog, a); + return EXIT_FAILURE; + } + } + } + break; + + case 'M': + if (!opt_arg || strncmp(opt_arg, "O=Deparse", strlen(opt_arg))) { + goto invalid_option; + } + Opt.deparse = 1; + break; + + case 'O': + Opt.unoptimize = 1; + break; + + case '\0': + c = opt_err; + goto invalid_option; + + default: + NOTREACHED; + } + } + argc -= opt_ind; + argv += opt_ind; + + randseed(); + + atechit(xend); + io_init(); + atechit(io_end); + + In = io_enter("(stdin)", stdin, IO_READ | IO_BUFFERED); + Out = io_enter("(stdout)", stdout, IO_WRITE | IO_TRUNCATE | IO_AUTOFLUSH); + Err = io_enter("(stderr)", stderr, IO_WRITE | IO_TRUNCATE | IO_AUTOFLUSH); + + if (!argv[0] || (argv[0][0] == '-' && argv[0][1] == '\0')) { + f = io_incr(In); + } else { + if (!(f = io_open(argv[0], IO_READ | IO_BUFFERED))) { + WARN(argv[0]); + return EXIT_FAILURE; + } + } + + /* ignore empty files */ + { + size_t p; + for (p = 0; isspace(c = io_peek(f, p)); ++p) + ; + if (c == EOF) { + if (io_err(f)) { + WARN(io_name(f, NULL)); + io_decr(f); + return EXIT_FAILURE; + } else { + io_decr(f); + return EXIT_SUCCESS; + } + } + } + + re_init(); + atechit(re_end); + atechit(var_end); + Var_plain = vr_new(xv_delete); + Var_hash = vr_new(xsh_delete); + + text_on(&text); + atechit(my_text_off); + ma_init(&Mars); + atechit(my_mars_end); + ve_init(&Venus); + atechit(my_venus_end); + + { + size_t tmp = 0; + char *eop = NULL; + char bkp = 00; + if (argv[0]) { + if (DIR_END && (eop = s_lastof(argv[0], DIR_END))) { + size_t i; + bkp = eop[1]; + eop[1] = '\0'; + for (i = 0; inc_ludes[i]; ++i) { + if (inc_ludes[i][0] == '\0') { + inc_ludes[i] = argv[0]; + } + } + } + } + parse(f, &text, &tmp); + if (eop) { + eop[1] = bkp; + } + } + io_decr(f); + + expr_init(); + atechit(expr_end); + + compile(&text); + if (!Opt.unoptimize) { + transmogrify(&text); + } + + my_mars_end_flag = 1; + ma_end(&Mars); + + if (Opt.deparse) { + deparse(&text); + return 0; + } + + run(&text, argc, argv); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,5 @@ +main.o: main.c IO.h config.h Str.h atechit.h compile.h text.h op.h expr.h \ + re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + deparse.h inc.h main.h main_io.h main_label.h mars.h venus.h hash.h \ + main_opt.h main_var.h opt.h parse.h random.h run.h transmogrify.h \ + version.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,6 @@ +#ifndef MAIN_H_ +#define MAIN_H_ + +extern const char *Prog; + +#endif /* MAIN_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main_io.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,8 @@ +#ifndef MAIN_IO_H_ +#define MAIN_IO_H_ + +#include "IO.h" + +extern IO *In, *Out, *Err; + +#endif /* MAIN_IO_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main_label.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,10 @@ +#ifndef MAIN_LABEL_H_ +#define MAIN_LABEL_H_ + +#include "mars.h" +#include "venus.h" + +extern struct mars Mars; +extern struct venus Venus; + +#endif /* MAIN_LABEL_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main_opt.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,16 @@ +#ifndef MAIN_OPT_H_ +#define MAIN_OPT_H_ + +struct Options { + int deparse; + enum { + DBG_OPS = 1, + DBG_HASH = 2 * DBG_OPS, + DBG_REGEX = 2 * DBG_HASH + } debug; + int unoptimize; +}; + +extern struct Options Opt; + +#endif /* MAIN_OPT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/main_var.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,8 @@ +#ifndef MAIN_VAR_H_ +#define MAIN_VAR_H_ + +#include "variable.h" + +extern t_vr_container *Var_plain, *Var_hash; + +#endif /* MAIN_VAR_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/mars.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,85 @@ +#include "Str.h" +#include "mars.h" +#include "op.h" +#include "xmalloc.h" + +enum {MAGIC = 128}; + +static void null(struct mars **p, size_t n) { + for (; n; --n) { + p[n - 1] = NULL; + } +} + +void ma_init(struct mars *m) { + m->data = NULL; + m->table = xmalloc(m->size = MAGIC, sizeof *m->table); + null(m->table, m->size); +} + +void ma_end(struct mars *m) { + for (; m->size; --m->size) { + if (m->table[m->size - 1]) { + ma_end(m->table[m->size - 1]); + xfree(m->table[m->size - 1]); + } + } + xfree(m->table); +} + +int ma_enter(struct mars *m, const String *key, struct op *value) { + size_t p; + + for (p = 0; p < St_len(key); ++p) { + size_t tmp = ST_INDEX(key, p); + if (m->size <= tmp) { + m->table = xrealloc(m->table, m->size * 2); + null(m->table + m->size, m->size); + m->size *= 2; + } + if (!m->table[tmp]) { + m->table[tmp] = xmalloc(1, sizeof *m->table[tmp]); + ma_init(m->table[tmp]); + } + m = m->table[tmp]; + } + + if (m->data) { + return -1; + } + m->data = value; + return 0; +} + +int ma_exists(const struct mars *m, const String *key) { + size_t p; + const struct op *ret = NULL; + + for (p = 0; p < St_len(key); ++p) { + size_t tmp = ST_INDEX(key, p); + ret = m->data; + if (tmp >= m->size || !m->table[tmp]) { + return 0; + } + m = m->table[tmp]; + } + return ret != NULL; +} + +struct op *ma_find(const struct mars *m, String *key) { + size_t p; + struct op *ret = NULL; + + for (p = 0; p < St_len(key); ++p) { + size_t tmp = ST_INDEX(key, p); + ret = m->data; + if (tmp >= m->size || !m->table[tmp]) { + break; + } + m = m->table[tmp]; + } + if (ret) { + St_del(key, 0, p); + } + return ret; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/mars.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +mars.o: mars.c Str.h config.h mars.h op.h IO.h expr.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/mars.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,21 @@ +#ifndef MARS_H_ +#define MARS_H_ + +#include "Str.h" +#include "op.h" + +#include <stddef.h> + +struct mars { + size_t size, length; + struct mars **table; + struct op *data; +}; + +void ma_init(struct mars *); +void ma_end(struct mars *); +int ma_enter(struct mars *, const String *, struct op *); +int ma_exists(const struct mars *, const String *); +struct op *ma_find(const struct mars *, String *); + +#endif /* MARS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/match.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,147 @@ +#include "IO.h" +#include "Str.h" +#include "main_io.h" +#include "main_opt.h" +#include "match.h" +#include "re.h" +#include "run.h" +#include "val.h" + +void do_match(struct val *v, t_regex *re) { + size_t mstart, mend; + size_t i; + size_t bra; + + if (V_EXT_P(v)) { + if (Opt.debug & DBG_REGEX) { + V_STR(v); + io_write_s(Err, "match: <<"); + io_write_m(Err, ko_ptr(v->ko), ko_length(v->ko)); + io_write_m(Err, "\n", 1); + } + + if (!(io_bufred(v->magic.ext) && re_iomatch(re, v->magic.ext, &mstart, &mend))) { + if (Opt.debug & DBG_REGEX) { + io_write_s(Err, "...failed\n"); + } + while (Interp.match.length) { + --Interp.match.length; + v_end(&Interp.match.matches[Interp.match.length]); + } + v->type = V_UNDEF; + return; + } + + if (Opt.debug & DBG_REGEX) { + io_write_s(Err, "...success!\n"); + } + v_set_n(&Interp.result, mend); + + bra = re_cabra(re); + if (Interp.match.size < bra) { + Interp.match.matches = xrealloc(Interp.match.matches, Interp.match.size = bra); + } + if (Interp.m_start.size < bra) { + Interp.m_start.index = xrealloc(Interp.m_start.index, Interp.m_start.size = bra); + } + if (Interp.m_end.size < bra) { + Interp.m_end.index = xrealloc(Interp.m_end.index, Interp.m_end.size = bra); + } + + for (i = 0; i < bra; ++i) { + size_t ms, me; + + if (re_backref(re, i, &ms, &me)) { + if (i < Interp.match.length) { + v_set_undef(&Interp.match.matches[i]); + } else { + v_init(&Interp.match.matches[Interp.match.length++]); + } + Interp.m_start.index[i] = -1; + Interp.m_end.index[i] = -1; + } else { + if (i >= Interp.match.length) { + v_init(&Interp.match.matches[Interp.match.length++]); + } + v_set_m(&Interp.match.matches[i], io_bufptr(v->magic.ext) + ms, me - ms); + Interp.m_start.index[i] = ms; + Interp.m_end.index[i] = me; + } + } + + io_read(v->magic.ext, NULL, mend); + V_xxx_OFF(v); + } else { + String tmp; + + V_STR(v); + V_xxx_OFF(v); + + St_fake(&tmp, (char *)ko_ptr(v->ko), ko_length(v->ko)); + + if (Opt.debug & DBG_REGEX) { + io_write_s(Err, "match: \""); + io_write(Err, &tmp); + io_write_s(Err, "\"\n"); + } + + if (!re_match(re, &tmp, &mstart, &mend)) { + if (Opt.debug & DBG_REGEX) { + io_write_s(Err, "...failed\n"); + } + while (Interp.match.length) { + --Interp.match.length; + v_end(&Interp.match.matches[Interp.match.length]); + } + v->type = V_UNDEF; + return; + } + + if (Opt.debug & DBG_REGEX) { + io_write_s(Err, "...success!\n"); + } + v_set_n(&Interp.result, mend); + + bra = re_cabra(re); + if (Interp.match.size < bra) { + Interp.match.matches = xrealloc(Interp.match.matches, Interp.match.size = bra); + } + if (Interp.m_start.size < bra) { + Interp.m_start.index = xrealloc(Interp.m_start.index, Interp.m_start.size = bra); + } + if (Interp.m_end.size < bra) { + Interp.m_end.index = xrealloc(Interp.m_end.index, Interp.m_end.size = bra); + } + + for (i = 0; i < bra; ++i) { + size_t ms, me; + + if (re_backref(re, i, &ms, &me)) { + if (i < Interp.match.length) { + v_set_undef(&Interp.match.matches[i]); + } else { + v_init(&Interp.match.matches[Interp.match.length++]); + } + Interp.m_start.index[i] = -1; + Interp.m_end.index[i] = -1; + } else { + if (i >= Interp.match.length) { + v_init(&Interp.match.matches[Interp.match.length++]); + } + v_set_m(&Interp.match.matches[i], ko_ptr(v->ko) + ms, me - ms); + Interp.m_start.index[i] = ms; + Interp.m_end.index[i] = me; + } + } + } + + if (!mstart) { + ko_cpy_m(v->ko, "0.", 2); + v->num = 0.0; + v->type = V_STR_K | V_NUM_K; + return; + } + + v->num = mstart; + v->type = V_NUM_K; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/match.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +match.o: match.c IO.h config.h Str.h main_io.h main_opt.h match.h re.h \ + val.h kork.h list.h sub.h run.h op.h expr.h stack.h xmalloc.h strhash.h \ + variable.h text.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/match.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,9 @@ +#ifndef MATCH_H_ +#define MATCH_H_ + +#include "re.h" +#include "val.h" + +void do_match(struct val *, t_regex *); + +#endif /* MATCH_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/op.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,314 @@ +#include "IO.h" +#include "Str.h" +#include "expr.h" +#include "main_label.h" +#include "mars.h" +#include "op.h" + +#include <ctype.h> +#include <stddef.h> +#include <string.h> + +void op_init(struct op *op) { + St_init(&op->txt); + op->type = OP_NOP; + op->arg = NULL; + op->arh.expr = NULL; + op->next = NULL; + op->line = 0; +} + +void op_end(struct op *op) { + St_clear(&op->txt); + free_expr(op->arg); + switch (op->type) { + case OP_ASSIGN: + case OP_CALL_BACK: + case OP_MODIFY: + case OP_PRINT: + case OP_PUTC: + case OP_SET_VAL: + case OP_TEMP: + free_expr(op->arh.expr); + break; + + default: + break; + } +} + +void op_getop(struct op *p) { + p->next = NULL; + + switch (ST_FIRSTCHAR(&p->txt)) { + case '#': + if (ST_INDEX(&p->txt, 1) == '!') { + p->type = OP_NOP; + break; + } + p->type = OP_SYSTEM; + St_shift(&p->txt); + p->arg = get_expr(p); + break; + + case 'A': + switch (ST_INDEX(&p->txt, 1)) { + case 'B': + if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "ABRUF", 5)) { + goto defualt; + } + p->type = OP_CALL_BACK; + St_del(&p->txt, 0, 5); + p->arh.expr = get_iobj(p); + p->arg = get_expr(p); + break; + + case 'N': + if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "ANRUF", 5)) { + goto defualt; + } + p->type = OP_CALL_DYN; + St_del(&p->txt, 0, 5); + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'C': + if (St_len(&p->txt) < 6 || St_ncmp_m(&p->txt, "CLAUDS", 6)) { + goto defualt; + } + p->type = OP_CLOSE; + St_del(&p->txt, 0, 6); + p->arg = get_expr(p); + break; + + case 'E': + switch (ST_INDEX(&p->txt, 1)) { + case 'L': + if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "ELSE", 4)) { + goto defualt; + } + p->type = OP_ELSE; + St_del(&p->txt, 0, 4); + break; + + case 'N': + if (St_len(&p->txt) >= 6 && St_ncmp_m(&p->txt, "END IF", 6) == 0) { + p->type = OP_FI; + break; + } + if (St_len(&p->txt) < 3 || St_ncmp_m(&p->txt, "END", 3)) { + goto defualt; + } + p->type = OP_EXIT; + St_del(&p->txt, 0, 3); + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'F': + switch (ST_INDEX(&p->txt, 1)) { + case 'I': + p->type = OP_FI; + break; + + case 'L': + if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "FLUSH", 5)) { + goto defualt; + } + p->type = OP_FLUSH; + St_del(&p->txt, 0, 5); + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'G': + if (ST_INDEX(&p->txt, 1) != 'O') { + goto defualt; + } + switch (ST_INDEX(&p->txt, 2)) { + case 'F': + if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "GOFOR", 5)) { + goto defualt; + } + p->type = OP_GOBACK; + St_del(&p->txt, 0, 5); + p->arg = get_expr(p); + break; + + case 'T': + if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "GOTO", 4)) { + goto defualt; + } + p->type = OP_GOTO; + St_del(&p->txt, 0, 4); + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'I': + switch (ST_INDEX(&p->txt, 1)) { + case 'A': + if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "IACS", 4)) { + goto defualt; + } + p->type = OP_THROW; + St_del(&p->txt, 0, 4); + p->arg = get_expr(p); + break; + + case 'F': + p->type = OP_IF; + St_del(&p->txt, 0, 2); + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'K': + if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "KTHX", 4)) { + goto defualt; + } + p->type = OP_RETURN; + St_del(&p->txt, 0, 4); + p->arg = get_expr(p); + break; + + case 'L': + if (ST_INDEX(&p->txt, 1) != 'E') { + goto defualt; + } + switch (ST_INDEX(&p->txt, 2)) { + case 'E': + if (ST_INDEX(&p->txt, 3) != 'T') { + goto defualt; + } + p->type = OP_TEMP; + St_del(&p->txt, 0, 4); + p->arh.expr = get_lval(p); + p->arg = get_expr(p); + break; + + case 'T': + p->type = OP_ASSIGN; + St_del(&p->txt, 0, 3); + p->arh.expr = get_lval(p); + St_shiftws(&p->txt); + if (p->arh.expr && ST_INDEX(&p->txt, 1) == '=' && OPERATOR_P(ST_FIRSTCHAR(&p->txt))) { + p->arh.expr->op = expr_binop(ST_FIRSTCHAR(&p->txt)); + St_del(&p->txt, 0, 2); + p->type = OP_MODIFY; + } + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'N': + if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "NEXT", 4)) { + goto defualt; + } else { + size_t tmp; + p->type = OP_NOP; + St_del(&p->txt, 0, 4); + tmp = St_shiftws(&p->txt); + if (!(p->next = ma_find(&Mars, &p->txt))) { + St_tac_m(&p->txt, "NEXT ", 4 + !!tmp); + p->arg = get_expr(p); + p->arh.expr = NULL; + p->type = OP_PRINT; + } + } + break; + + case 'R': + if (ST_INDEX(&p->txt, 1) != 'E') { + goto defualt; + } + switch (ST_INDEX(&p->txt, 2)) { + case 'M': + p->type = OP_NOP; + break; + + case 'S': + if (St_len(&p->txt) < 5 || St_ncmp_m(&p->txt, "RESET", 5)) { + goto defualt; + } + p->type = OP_RESET; + St_del(&p->txt, 0, 5); + p->arg = get_expr(p); + break; + + default: + goto defualt; + } + break; + + case 'S': + if (St_len(&p->txt) < 3 || St_ncmp_m(&p->txt, "SET", 3)) { + goto defualt; + } + p->type = OP_PUTC; + St_del(&p->txt, 0, 3); + p->arg = get_iobj(p); + p->arh.expr = NULL; + St_shiftws(&p->txt); + if (ST_FIRSTCHAR(&p->txt) == ',') { + St_shift(&p->txt); + p->arh.expr = p->arg; + p->arg = get_expr(p); + } + break; + + case 'W': + if (St_len(&p->txt) < 4 || St_ncmp_m(&p->txt, "WUNT", 4)) { + goto defualt; + } + p->type = OP_PRINT; + St_del(&p->txt, 0, 4); + p->arg = get_iobj(p); + p->arh.expr = NULL; + St_shiftws(&p->txt); + if (ST_FIRSTCHAR(&p->txt) != EOF) { + p->arh.expr = p->arg; + p->arg = get_expr(p); + } + break; + +defualt: + default: + if ((p->arh.op = ma_find(&Mars, &p->txt))) { + p->type = OP_CALL; + p->arg = get_expr(p); + } else { + p->type = OP_PRINT; + p->arg = get_expr(p); + p->arh.expr = NULL; + } + break; + } + + St_clear(&p->txt); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/op.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +op.o: op.c IO.h config.h Str.h expr.h op.h re.h stack.h xmalloc.h \ + strhash.h val.h kork.h list.h sub.h variable.h main_label.h mars.h \ + venus.h hash.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/op.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,67 @@ +#ifndef OP_H_ +#define OP_H_ + +#include "IO.h" +#include "Str.h" +#include "expr.h" + +#include <stddef.h> + +enum t_op { + OP_NOP, + OP_ASSIGN, + OP_CALL, + OP_CALL_BACK, + OP_CALL_DYN, + OP_CLOSE, + OP_ELSE, + OP_EXIT, + OP_FI, + OP_FLUSH, + OP_GOBACK, + OP_GOTO, + OP_HANG, + OP_IF, + OP_MODIFY, + OP_PRINT, + OP_PUTC, + OP_RESET, + OP_RETURN, + OP_SET_VAL, + OP_SYSTEM, + OP_TEMP, + OP_THROW +}; + +struct op { + enum t_op type; + struct expr *arg; + union { + struct expr *expr; + struct op *op; + } arh; + struct op *next; + String txt; + size_t line; +}; + +void op_init(struct op *); +void op_end(struct op *); +void op_getop(struct op *); + +#define OP_1ARG_P(op) \ +( \ + (op) == OP_CALL || (op) == OP_CALL_DYN || (op) == OP_CLOSE || \ + (op) == OP_EXIT || (op) == OP_FLUSH || (op) == OP_GOTO || \ + (op) == OP_IF || (op) == OP_RESET || (op) == OP_RETURN || \ + (op) == OP_SYSTEM || (op) == OP_THROW \ +) + +#define OP_2ARG_P(op) \ +( \ + (op) == OP_ASSIGN || (op) == OP_CALL_BACK || (op) == OP_MODIFY || \ + (op) == OP_PRINT || (op) == OP_PUTC || (op) == OP_SET_VAL || \ + (op) == OP_TEMP \ +) + +#endif /* OP_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/opt.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,51 @@ +#include "opt.h" + +#include <string.h> + +int opt_ind; +int opt_err; +const char *opt_arg; +static const char *nextchar; + +int opt_get(int argc, char *const *argv, const char *opts) { + const char *p; + + if (!nextchar || !*nextchar) { + if (opt_ind < argc) + ++opt_ind; + if (opt_ind >= argc || argv[opt_ind][0] != '-' || !argv[opt_ind][1]) { + return -1; + } + if (argv[opt_ind][1] == '-' && argv[opt_ind][2] == '\0') { + ++opt_ind; + return -1; + } + nextchar = argv[opt_ind] + 1; + } + + if ((p = strchr(opts, *nextchar)) && (*p != ':' || p == opts)) { + if (p[1] == ':') { + if (nextchar[1]) { + opt_arg = nextchar + 1; + } else if (opt_ind + 1 >= argc) { + opt_arg = NULL; + } else { + opt_arg = argv[++opt_ind]; + } + nextchar = NULL; + } else { + ++nextchar; + } + return p[0]; + } + + opt_err = *nextchar++; + return '\0'; +} + +#if 0 +void opt_reset(void) { + opt_ind = 0; + nextchar = NULL; +} +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/opt.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +opt.o: opt.c opt.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/opt.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,13 @@ +#ifndef OPT_H_ +#define OPT_H_ + +extern int opt_ind; +extern int opt_err; +extern const char *opt_arg; + +int opt_get(int, char *const *, const char *); +#if 0 +void opt_reset(void); +#endif + +#endif /* OPT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/parse.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,210 @@ +#include "IO.h" +#include "inc.h" +#include "main.h" +#include "main_label.h" +#include "mars.h" +#include "op.h" +#include "parse.h" +#include "text.h" +#include "venus.h" + +#include <ctype.h> +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static void skipline(IO *f) { + int c; + + for ( + c = io_peek(f, 0); + c != EOF && c != '\n'; + c = io_peek(f, 0) + ) { + if (c == 'R' && io_cmppeek(f, 0, "REM", 3) == 0) { + io_read(f, NULL, 3); + skipline(f); + } else { + io_getc(f); + } + } + if (c == '\n') { + io_getc(f); + } +} + +static IO *open_inc(const char *s, enum io_flags mode) { + size_t i; + String cur; + + St_init(&cur); + for (i = 0; inc_ludes[i]; ++i) { + IO *tmp; + + St_cpy_s(&cur, s); + St_tac_s(&cur, inc_ludes[i]); + if ((tmp = io_open(St_ptr(&cur), mode))) { + St_clear(&cur); + return tmp; + } + } + St_clear(&cur); + + return NULL; +} + +void parse(IO *f, struct text *text, size_t *line) { + int c; + + while ((c = io_peek(f, 0)) != EOF) { + struct op node; + String label; + int is_static = 0; + + for ( + ; + c != EOF && c != '\n' && isspace(c); + c = io_peek(f, 0) + ) { + io_getc(f); + } + if (c == EOF) { + break; + } + + if (io_cmppeek(f, 0, "INSERT", 6) == 0) { + size_t start; + size_t end; + String ifname; + IO *ifp; + int inc; + + if (io_cmppeek(f, 6, " DA", 3) == 0) { + inc = 0; + start = 9; + } else { + inc = 1; + start = 6; + } + + for ( + ; + (c = io_peek(f, start)) != '\n' && isspace(c); + ++start + ) + ; + if (c == '\n' || c == EOF) { + goto no_insert; + } + for ( + end = start + 1; + (c = io_peek(f, end)) != '\n' && c != EOF; + ++end + ) + ; + for ( + ; + end > start && isspace(io_peek(f, end - 1)); + --end + ) + ; + if (io_cmppeek(f, end - 4, "HERE", 4)) { + goto no_insert; + } + for ( + end -= 4; + isspace(io_peek(f, end - 1)); + --end + ) + ; + io_read(f, NULL, start); + St_init(&ifname); + if (end > start) { + io_read(f, &ifname, end - start); + } + if (!(ifp = (inc ? open_inc : io_open)(St_ptr(&ifname), IO_READ | IO_BUFFERED))) { + fprintf(stderr, "%s: %s: %s\n", Prog, St_ptr(&ifname), strerror(errno)); + St_clear(&ifname); + exit(EXIT_FAILURE); + } else { + parse(ifp, text, line); + io_decr(ifp); + } + St_clear(&ifname); + io_getline(f, NULL); + continue; + } +no_insert: + + op_init(&node); + node.line = *line; + + St_init(&label); + if (io_cmppeek(f, 0, "FOR", 3) == 0) { + size_t p; + for (p = 3; (c = io_peek(f, p)) != '\n' && isspace(c); ++p) + ; + if (c != EOF && c != '\n') { + St_cat_c(&label, c); + for (++p; (c = io_peek(f, p)) != EOF && !isspace(c); ++p) { + St_cat_c(&label, c); + } + if (!ma_exists(&Mars, &label)) { + is_static = 1; + io_read(f, NULL, p); + } else { + St_zero(&label); + } + } + } else { + for (; (c = io_peek(f, 0)) == '0'; io_getc(f)) + ; + for (; isdigit(c); c = io_peek(f, 0)) { + St_cat_c(&label, c); + io_getc(f); + } + } + + for ( + c = io_peek(f, 0); + c != EOF && c != '\n' && isspace(c); + c = io_peek(f, 0) + ) { + io_getc(f); + } + + if (io_cmppeek(f, 0, "REM", 3) == 0) { + io_read(f, &node.txt, 3); + skipline(f); + } else { + size_t pos; + + io_getline(f, &node.txt); + if ((pos = St_rstr_m(&node.txt, "?\?/\n", 4)) + 1u && pos + 4u == St_len(&node.txt)) { + String buf; + St_init(&buf); + + do { + io_getline(f, &buf); + St_del(&node.txt, St_len(&node.txt) - 4u, 4); + St_cat(&node.txt, &buf); + } while ((pos = St_rstr_m(&node.txt, "?\?/\n", 4)) + 1u && pos + 4u == St_len(&node.txt)); + St_clear(&buf); + } + } + + { + struct op *tmp; + tmp = text_push(text, &node); + if (is_static) { + ma_enter(&Mars, &label, tmp); + } else { + ve_enter(&Venus, &label, tmp); + ++*line; + } + } + St_clear(&label); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/parse.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +parse.o: parse.c IO.h config.h Str.h inc.h main.h main_label.h mars.h \ + op.h expr.h re.h stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h \ + variable.h venus.h hash.h parse.h text.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/parse.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,11 @@ +#ifndef PARSE_H_ +#define PARSE_H_ + +#include "IO.h" +#include "text.h" + +#include <stdio.h> + +void parse(IO *, struct text *, size_t *); + +#endif /* PARSE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/pp.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,957 @@ +#include "IO.h" +#include "Str.h" +#include "kork.h" +#include "list.h" +#include "main_io.h" +#include "main_opt.h" +#include "match.h" +#include "pp.h" +#include "re.h" +#include "run.h" +#include "val.h" +#include "xmalloc.h" + +#include <ctype.h> +#include <errno.h> +#include <float.h> +#include <math.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +void pp_abs(struct val *v) { + V_NUM(v); + v_set_n(v, fabs(v->num)); +} + +void pp_acos(struct val *v) { + V_NUM(v); + v_set_n(v, acos(v->num)); +} + +void pp_asin(struct val *v) { + V_NUM(v); + v_set_n(v, asin(v->num)); +} + +void pp_atan(struct val *v) { + V_NUM(v); + v_set_n(v, atan(v->num)); +} + +void pp_atan2(struct val *v) { + if (!V_LIST_P(v) || li_length(v->magic.list) != 2) { + v_set_undef(v); + #ifdef EINVAL + errno = EINVAL; + #endif + return; + } else { + struct val *const a = li_at(v->magic.list, 0); + struct val *const b = li_at(v->magic.list, 1); + V_NUM(a); + V_NUM(b); + v_set_n(v, atan2(a->num, b->num)); + } +} + +void pp_chr(struct val *v) { + V_NUM(v); + V_xxx_OFF(v); + ko_cpy_c(v->ko, (unsigned char)(v->num + .5)); + v->type = V_STR_K; +} + +void pp_cos(struct val *v) { + V_NUM(v); + v_set_n(v, cos(v->num)); +} + +void pp_defined(struct val *v) { + if (v->type != V_UNDEF) { + v_set_n(v, 1.0); + } +} + +void pp_eof(struct val *v) { + if (!V_EXT_P(v)) { + v_set_undef(v); + #ifdef EBADF + errno = EBADF; + #endif + return; + } + if (io_eof(v->magic.ext)) { + v_set_n(v, 1.0); + } else { + v_set_m(v, "", 0); + } +} + +void pp_error(struct val *v) { + if (!V_EXT_P(v)) { + v_set_undef(v); + #ifdef EBADF + errno = EBADF; + #endif + return; + } + if (io_err(v->magic.ext)) { + v_set_n(v, 1.0); + } else { + v_set_m(v, "", 0); + } +} + +void pp_escape(struct val *v) { + String tmp; + size_t i; + + V_STR(v); + V_xxx_OFF(v); + St_init(&tmp); + St_cpy(&tmp, ko_str(v->ko)); + ko_zero(v->ko); + for (i = St_len(&tmp); i; ) { + --i; + if (!(ST_INDEX(&tmp, i) == '_' || isalnum(ST_INDEX(&tmp, i)))) { + ko_cat_c(v->ko, '!'); + } + ko_cat_c(v->ko, ST_INDEX(&tmp, i)); + } + St_clear(&tmp); + ko_reverse(v->ko); + v->type = V_STR_K; +} + +void pp_getc(struct val *v) { + int c; + + if (!V_EXT_P(v)) { + V_xxx_OFF(v); + v->type = V_UNDEF; + #ifdef EBADF + errno = EBADF; + #endif + return; + } + c = io_getc(v->magic.ext); + #if EOF != -1 + if (c == EOF) { + c = -1; + } + #endif + v_set_n(v, c); +} + +void pp_getenv(struct val *v) { + const char *const tmp = getenv(v_sptr(v, NULL)); + if (tmp) { + v_set_m(v, tmp, strlen(tmp)); + } else { + V_xxx_OFF(v); + v->type = V_UNDEF; + } +} + +void pp_gets(struct val *v) { + + if (!V_EXT_P(v)) { + V_xxx_OFF(v); + v->type = V_UNDEF; + #ifdef EBADF + errno = EBADF; + #endif + return; + } + + if (ko_getline(v->magic.ext, v->ko) + 1u) { + V_xxx_OFF(v); + v->type = V_STR_K; + } else { + V_xxx_OFF(v); + v->type = V_UNDEF; + } +} + +void pp_int(struct val *v) { + V_NUM(v); + v_set_n(v, floor(v->num + .5)); +} + +void pp_io(struct val *v) { + if (V_EXT_P(v)) { + v_set_n(v, 1.0); + } else { + v_set_m(v, "", 0); + } +} + +void pp_length(struct val *v) { + if (V_LIST_P(v)) { + v_set_n(v, li_length(v->magic.list)); + return; + } + v_set_n(v, ko_length(v_kork(v))); +} + +void pp_log(struct val *v) { + V_NUM(v); + v_set_n(v, log(v->num)); +} + +void pp_log10(struct val *v) { + V_NUM(v); + v_set_n(v, log10(v->num)); +} + +void pp_lower(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + ko_lower(v->ko); +} + +void pp_moend(struct val *v) { + size_t n; + + V_NUM(v); + n = RINT(v->num); + if (n < Interp.m_end.size) { + v_set_n(v, Interp.m_end.index[n]); + } else { + v_set_undef(v); + } +} + +void pp_mostart(struct val *v) { + size_t n; + + V_NUM(v); + n = RINT(v->num); + if (n < Interp.m_start.size) { + v_set_n(v, Interp.m_start.index[n]); + } else { + v_set_undef(v); + } +} + +void pp_neg(struct val *v) { + V_NUM(v); + V_xxx_OFF(v); + v->num = -v->num; + v->type = V_NUM_K; +} + +void pp_not(struct val *v) { + if (v_true(v)) { + v_set_m(v, "", 0); + } else { + v_set_n(v, 1.0); + } +} + +void pp_num(struct val *v) { + V_NUM(v); + V_xxx_OFF(v); + v->type = V_NUM_K; +} + +void pp_open(struct val *v) { + IO *fh; + struct val *name, *mode; + enum io_flags flags; + + if (!V_LIST_P(v) || li_length(v->magic.list) != 2) { + v_set_undef(v); + #ifdef ENOENT + errno = ENOENT; + #endif + return; + } + + name = li_at(v->magic.list, 0); + V_STR(name); + if (ko_chr(name->ko, '\0') + 1u) { + v_set_undef(v); + #ifdef ENOENT + errno = ENOENT; + #endif + return; + } + + mode = li_at(v->magic.list, 1); + flags = 0; + V_STR(mode); + + if (ko_chr(mode->ko, 'A') + 1u) { + flags |= IO_APPEND; + if (ko_chr(mode->ko, '+') + 1u) { + flags |= IO_READ; + } + } else if (ko_chr(mode->ko, 'W') + 1u) { + flags |= IO_WRITE | IO_TRUNCATE; + if (ko_chr(mode->ko, '+') + 1u) { + flags |= IO_READ; + } + } else { + flags |= IO_READ; + if (ko_chr(mode->ko, '+') + 1u) { + flags |= IO_WRITE; + } else if (ko_chr(mode->ko, 'Z') + 1u) { + flags |= IO_BUFFERED; + } + } + + if (ko_chr(mode->ko, 'B') + 1u) { + flags |= IO_BINARY; + } + if ((flags & IO_WRITE || flags & IO_APPEND) && ko_chr(mode->ko, 'F') + 1u) { + flags |= IO_AUTOFLUSH; + } + + if (!(fh = io_open(ko_szp(name->ko), flags))) { + v_set_undef(v); + return; + } + + v_set_io(v, fh); +} + +void pp_openr(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + if (ko_chr(v->ko, '\0') + 1u) { + v->type = V_UNDEF; + #ifdef ENOENT + errno = ENOENT; + #endif + } else if ((v->magic.ext = io_open(ko_szp(v->ko), IO_READ | IO_BINARY))) { + v->type = V_EXT_K; + } else { + v->type = V_UNDEF; + } +} + +void pp_openw(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + if (ko_chr(v->ko, '\0') + 1u) { + v->type = V_UNDEF; + #ifdef ENOENT + errno = ENOENT; + #endif + } else if ((v->magic.ext = io_open(ko_szp(v->ko), IO_WRITE | IO_TRUNCATE | IO_BINARY | IO_AUTOFLUSH))) { + v->type = V_EXT_K; + } else { + v->type = V_UNDEF; + } +} + +void pp_ord(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + if (ko_length(v->ko)) { + v->num = ko_at(v->ko, 0); + v->type = V_NUM_K; + } else { + v->type = V_UNDEF; + } +} + +void pp_quote(struct val *v) { + String tmp; + size_t i; + + V_STR(v); + V_xxx_OFF(v); + St_init(&tmp); + St_cpy_m(&tmp, ko_ptr(v->ko), ko_length(v->ko)); + ko_zero(v->ko); + for (i = 0; i < St_len(&tmp); ++i) { + if (!(ST_INDEX(&tmp, i) == '_' || isalnum(ST_INDEX(&tmp, i)))) { + ko_cat_c(v->ko, '\\'); + } + ko_cat_c(v->ko, ST_INDEX(&tmp, i)); + } + St_clear(&tmp); + v->type = V_STR_K; +} + +void pp_remove(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + if (ko_chr(v->ko, '\0') + 1u) { + v->type = V_UNDEF; + #ifdef ENOENT + errno = ENOENT; + #endif + return; + } + + if (remove(ko_szp(v->ko))) { + v_set_m(v, "", 0); + } else { + v_set_n(v, 1.0); + } +} + +void pp_rename(struct val *v) { + struct val *from, *to; + + if (!V_LIST_P(v) || li_length(v->magic.list) != 2) { + v_set_undef(v); + #ifdef ENOENT + errno = ENOENT; + #endif + return; + } + + from = li_at(v->magic.list, 0); + V_STR(from); + if (ko_chr(from->ko, '\0') + 1u) { + v_set_undef(v); + #ifdef ENOENT + errno = ENOENT; + #endif + return; + } + + to = li_at(v->magic.list, 1); + V_STR(to); + if (ko_chr(to->ko, '\0') + 1u) { + v_set_undef(v); + #ifdef EINVAL + errno = EINVAL; + #endif + return; + } + + if (rename(ko_szp(from->ko), ko_szp(to->ko))) { + v_set_m(v, "", 0); + } else { + v_set_n(v, 1.0); + } +} + +void pp_reverse(struct val *v) { + if (V_LIST_P(v)) { + li_reverse(v->magic.list); + v->type = V_LIST_K; + return; + } + V_STR(v); + V_xxx_OFF(v); + ko_reverse(v->ko); + v->type = V_STR_K; +} + +void pp_seek(struct val *v) { + struct val *fh, *tmp; + long off; + enum io_whence whence = IOS_START; + + if (!V_LIST_P(v) || li_length(v->magic.list) < 2 || li_length(v->magic.list) > 3) { + v_set_undef(v); + #ifdef EINVAL + errno = EINVAL; + #endif + return; + } + + fh = li_at(v->magic.list, 0); + if (!V_EXT_P(fh)) { + v_set_undef(v); + #ifdef EBADF + errno = EBADF; + #endif + return; + } + + tmp = li_at(v->magic.list, 1); + V_NUM(tmp); + off = RINT(tmp->num); + + if ((tmp = li_at(v->magic.list, 2))) { + V_NUM(tmp); + switch ((long)RINT(tmp->num)) { + case 0: whence = IOS_START; break; + case 1: whence = IOS_CUR; break; + case 2: whence = IOS_END; break; + default: + v_set_undef(v); + #ifdef EINVAL + errno = EINVAL; + #endif + return; + } + } + + v_set_n(v, io_seek(fh->magic.ext, off, whence)); +} + +void pp_sin(struct val *v) { + V_NUM(v); + v_set_n(v, sin(v->num)); +} + +void pp_sqrt(struct val *v) { + V_NUM(v); + V_xxx_OFF(v); + v->num = sqrt(v->num); + v->type = V_NUM_K; +} + +void pp_str(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + v->type |= V_STR_K; +} + +void pp_tan(struct val *v) { + V_NUM(v); + v_set_n(v, tan(v->num)); +} + +void pp_tell(struct val *v) { + if (!V_EXT_P(v)) { + v_set_undef(v); + #ifdef EBADF + errno = EBADF; + #endif + return; + } + v_set_n(v, io_tell(v->magic.ext)); +} + +void pp_typeof(struct val *v) { + if (V_SUB_P(v)) { + v_set_m(v, "stuff", 5); + } else if (V_EXT_P(v)) { + v_set_m(v, "stream", 6); + } else if (V_LIST_P(v)) { + v_set_m(v, "list", 4); + } else if (V_NUM_P(v)) { + v_set_m(v, "number", 6); + } else if (V_STR_P(v)) { + v_set_m(v, "string", 6); + } else { + v_set_m(v, "nothing", 7); + } +} + +void pp_upper(struct val *v) { + V_STR(v); + V_xxx_OFF(v); + ko_upper(v->ko); +} + +#define NUMB(expr) \ +do { \ + V_NUM(b); \ + V_NUM(v); \ + v_set_n(v, expr); \ +} while (0) + +#define ARITH(op) NUMB(v->num op b->num) + +void pp_add(struct val *v, struct val *b) { + ARITH(+); +} + +#define LOGIC(init, cond) \ +do { \ + init; \ + if (cond) { \ + v_set_n(v, 1.0); \ + } else { \ + v_set_m(v, "", 0); \ + } \ +} while (0) + +void pp_and(struct val *v, struct val *b) { + LOGIC((void)0, v_true(v) && v_true(b)); +} + +void pp_comma(struct val *v, struct val *b) { + v_set(v, b); +} + +void pp_concat(struct val *v, struct val *b) { + v_cat(v, b); +} + +void pp_div(struct val *v, struct val *b) { + ARITH(/); +} + +#define CMP_LS(op) LOGIC((void)0, v_cmp_ls(v, b) op 0) + +void pp_eq(struct val *v, struct val *b) { + CMP_LS(==); +} + +#define CMP_N(op) LOGIC(V_NUM(v); V_NUM(b), v->num op b->num) + +void pp_eq_n(struct val *v, struct val *b) { + if (V_EXT_P(v)) { + if (V_EXT_P(b)) { + LOGIC((void)0, v->magic.ext == b->magic.ext); + } else if (V_SUB_P(b)) { + goto false_cmp; + } else { + goto default_cmp; + } + } else if (V_SUB_P(v)) { + if (V_SUB_P(b)) { + LOGIC((void)0, v->magic.sub == b->magic.sub); + } else if (V_EXT_P(b)) false_cmp: { + LOGIC((void)0, 0); + } else { + goto default_cmp; + } + } else default_cmp: { + CMP_N(==); + } +} + +static const char xdigits[] = "0123456789" "abcdefghijklmnopqrstuvwxyz"; + +void pp_frombase(struct val *v, struct val *b) { + double p; + size_t i; + int base, sign; + const char *tmp; + + V_NUM(b); + V_STR(v); + V_xxx_OFF(v); + if (floor(b->num + .5) < 2. || floor(b->num + .5) > 36.) { + v->type = V_UNDEF; + return; + } + base = floor(b->num + .5); + ko_shiftws(v->ko); + + sign = 0; + if (ko_at(v->ko, 0) == '-') { + sign = 1; + ko_shift(v->ko, 1); + } else if (ko_at(v->ko, 0) == '+') { + ko_shift(v->ko, 1); + } + + p = 0.0; + for (i = 0; i < ko_length(v->ko); ++i) { + if ((tmp = strchr(xdigits, tolower(ko_at(v->ko, i)))) && + tmp - xdigits < base) { + p *= base; + p += tmp - xdigits; + } else { + break; + } + } + + if (i < ko_length(v->ko)) { + if (ko_at(v->ko, i) == '.') { + double shift = 1.0; + + for (++i; i < ko_length(v->ko); ++i) { + if ((tmp = strchr(xdigits, tolower(ko_at(v->ko, i)))) && + tmp - xdigits < base) { + shift *= base; + p *= base; + p += tmp - xdigits; + } else { + break; + } + } + + p /= shift; + } + } + + if (sign) { + p = -p; + } + v_set_n(v, p); +} + +void pp_gt(struct val *v, struct val *b) { + CMP_LS(>); +} + +void pp_gt_n(struct val *v, struct val *b) { + CMP_N(>); +} + +void pp_lt(struct val *v, struct val *b) { + CMP_LS(<); +} + +void pp_lt_n(struct val *v, struct val *b) { + CMP_N(<); +} + +void pp_match(struct val *v, struct val *b) { + t_regex *re; + + V_STR(b); + re = re_compile(ko_str(b->ko)); + do_match(v, re); + re_free(re); +} + +void pp_mod(struct val *v, struct val *b) { + NUMB(fmod(v->num, b->num)); +} + +void pp_mult(struct val *v, struct val *b) { + ARITH(*); +} + +void pp_ne(struct val *v, struct val *b) { + CMP_LS(!=); +} + +void pp_ne_n(struct val *v, struct val *b) { + if (V_EXT_P(v)) { + if (V_EXT_P(b)) { + LOGIC((void)0, v->magic.ext != b->magic.ext); + } else if (V_SUB_P(b)) { + goto true_cmp; + } else { + goto default_cmp; + } + } else if (V_SUB_P(v)) { + if (V_SUB_P(b)) { + LOGIC((void)0, v->magic.sub != b->magic.sub); + } else if (V_EXT_P(b)) true_cmp: { + LOGIC((void)0, 1); + } else { + goto default_cmp; + } + } else default_cmp: { + CMP_N(!=); + } +} + +void pp_or(struct val *v, struct val *b) { + LOGIC((void)0, v_true(v) || v_true(b)); +} + +void pp_pop(struct val *v, struct val *b) { + long p; + + V_NUM(b); + p = RINT(b->num); + + if (V_LIST_P(v)) { + v->type = V_LIST_K; + if (p < 0) { + p += li_length(v->magic.list); + } + if (p < 0) { + p = 0; + } + if ((size_t)p >= li_length(v->magic.list)) { + return; + } + li_trunc(v->magic.list, p); + return; + } + + V_STR(v); + V_xxx_OFF(v); + v->type = V_STR_K; + if (p < 0) { + p += ko_length(v->ko); + } + if (p < 0) { + p = 0; + } + if ((size_t)p >= ko_length(v->ko)) { + return; + } + ko_trunc(v->ko, p); +} + +void pp_pow(struct val *v, struct val *b) { + NUMB(pow(v->num, b->num)); +} + +void pp_read(struct val *v, struct val *b) { + long n; + + if (V_SUB_P(v)) { + const size_t curdepth = depth_get(); + stack_store(&Interp.arg, b); + eval_into(sub_expr(v->magic.sub), v); + depth_restore(curdepth); + return; + } + + if (V_EXT_P(v)) { + V_NUM(b); + ko_read(v->magic.ext, v->ko, b->num < 0.0 ? (size_t)-1 : b->num + .5); + V_xxx_OFF(v); + v->type = V_STR_K; + return; + } + + if (V_LIST_P(v)) { + struct val *ptr; + V_NUM(b); + n = RINT(b->num); + if (n < 0) { + n += li_length(v->magic.list); + } + + if (n >= 0 && (ptr = li_at(v->magic.list, n))) { + struct list *tmp = li_dup(v->magic.list); + v_set(v, ptr); + li_delete(tmp); + } else { + v_set_undef(v); + } + return; + } + + V_STR(v); + V_xxx_OFF(v); + V_NUM(b); + n = RINT(b->num); + if (n < 0) { + n += ko_length(v->ko); + } + if (n >= 0 && (size_t)n < ko_length(v->ko)) { + ko_shift(v->ko, n); + ko_trunc(v->ko, 1); + v->type = V_STR_K; + } else { + v->type = V_UNDEF; + } +} + +void pp_shift(struct val *v, struct val *b) { + long p; + + V_NUM(b); + p = RINT(b->num); + + if (V_LIST_P(v)) { + v->type = V_LIST_K; + if (p < 0) { + p += li_length(v->magic.list); + } + if (p <= 0) { + return; + } + if ((size_t)p >= li_length(v->magic.list)) { + li_zero(v->magic.list); + } else { + li_shift(v->magic.list, p); + } + return; + } + + V_STR(v); + V_xxx_OFF(v); + v->type = V_STR_K; + if (p < 0) { + p += ko_length(v->ko); + } + if (p <= 0) { + return; + } + if ((size_t)p >= ko_length(v->ko)) { + ko_zero(v->ko); + } else { + ko_shift(v->ko, p); + } +} + +void pp_sub(struct val *v, struct val *b) { + ARITH(-); +} + +void pp_tobase(struct val *v, struct val *b) { + double p; + int base, sign; + size_t i; + + V_NUM(b); + V_NUM(v); + V_xxx_OFF(v); + + if (floor(b->num + .5) < 2. || floor(b->num + .5) > 36.) { + v->type = V_UNDEF; + return; + } + base = floor(b->num + .5); + + sign = 0; + if (v->num < 0.) { + v->num = -v->num; + sign = 1; + } + + p = v->num; + ko_zero(v->ko); + + if (floor(p) < p) { + double foo, bar; + size_t rounds; + + foo = 1 + floor(log(pow(10, DBL_DIG)) / log(base)); + bar = p > 0. ? 1 + floor(log(p) / log(base)) : 0.; + if (bar >= foo) { + rounds = 0; + } else { + rounds = foo - bar; + } + + for (i = 0; i < rounds; ++i) { + p *= base; + if (floor(p) >= p) { + ++i; + break; + } + } + + p = floor(p); + while (i--) { + int c; + c = fmod(p, base); + p = floor(p / base); + if (c >= 0) { + ko_cat_c(v->ko, xdigits[c]); + } + } + } + + while (ko_at(v->ko, 0) == '0') { + ko_shift(v->ko, 1); + } + + if (ko_length(v->ko)) { + ko_cat_c(v->ko, '.'); + } + + while (p > 0.) { + int c; + c = fmod(p, base); + p = floor(p / base); + if (c >= 0) { + ko_cat_c(v->ko, xdigits[c]); + } + } + + if (!ko_length(v->ko) || ko_lastchar(v->ko) == '.') { + ko_cat_c(v->ko, '0'); + } + if (sign) { + ko_cat_c(v->ko, '-'); + } + + v->type = V_STR_K; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/pp.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +pp.o: pp.c IO.h config.h Str.h kork.h list.h main_io.h main_opt.h match.h \ + re.h val.h sub.h pp.h run.h op.h expr.h stack.h xmalloc.h strhash.h \ + variable.h text.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/pp.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,81 @@ +#ifndef PP_H_ +#define PP_H_ + +#include "val.h" + +#define DECL_PP1(name) void name(struct val *) + +DECL_PP1(pp_abs); +DECL_PP1(pp_acos); +DECL_PP1(pp_asin); +DECL_PP1(pp_atan); +DECL_PP1(pp_atan2); +DECL_PP1(pp_chr); +DECL_PP1(pp_cos); +DECL_PP1(pp_defined); +DECL_PP1(pp_eof); +DECL_PP1(pp_error); +DECL_PP1(pp_escape); +DECL_PP1(pp_getc); +DECL_PP1(pp_getenv); +DECL_PP1(pp_gets); +DECL_PP1(pp_int); +DECL_PP1(pp_io); +DECL_PP1(pp_length); +DECL_PP1(pp_log); +DECL_PP1(pp_log10); +DECL_PP1(pp_lower); +DECL_PP1(pp_moend); +DECL_PP1(pp_mostart); +DECL_PP1(pp_neg); +DECL_PP1(pp_not); +DECL_PP1(pp_num); +DECL_PP1(pp_open); +DECL_PP1(pp_openr); +DECL_PP1(pp_openw); +DECL_PP1(pp_ord); +DECL_PP1(pp_quote); +DECL_PP1(pp_remove); +DECL_PP1(pp_rename); +DECL_PP1(pp_reverse); +DECL_PP1(pp_seek); +DECL_PP1(pp_sin); +DECL_PP1(pp_sqrt); +DECL_PP1(pp_str); +DECL_PP1(pp_tan); +DECL_PP1(pp_tell); +DECL_PP1(pp_typeof); +DECL_PP1(pp_upper); + +#undef DECL_PP1 + +#define DECL_PP2(name) void name(struct val *, struct val *) + +DECL_PP2(pp_add); +DECL_PP2(pp_and); +DECL_PP2(pp_comma); +DECL_PP2(pp_concat); +DECL_PP2(pp_div); +DECL_PP2(pp_eq); +DECL_PP2(pp_eq_n); +DECL_PP2(pp_frombase); +DECL_PP2(pp_gt); +DECL_PP2(pp_gt_n); +DECL_PP2(pp_lt); +DECL_PP2(pp_lt_n); +DECL_PP2(pp_match); +DECL_PP2(pp_mod); +DECL_PP2(pp_mult); +DECL_PP2(pp_ne); +DECL_PP2(pp_ne_n); +DECL_PP2(pp_or); +DECL_PP2(pp_pop); +DECL_PP2(pp_pow); +DECL_PP2(pp_read); +DECL_PP2(pp_shift); +DECL_PP2(pp_sub); +DECL_PP2(pp_tobase); + +#undef DECL_PP2 + +#endif /* PP_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/random.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,27 @@ +#include "config.h" +#include "random.h" + +#include <stdio.h> +#include <stdlib.h> +#include <time.h> + +void randseed(void) { + unsigned seed; + + seed = time(NULL); + #if HAVE_DEV_URANDOM_P + { + FILE *fp; + + if ((fp = fopen("/dev/urandom", "rb"))) { + fread(&seed, sizeof seed, 1, fp); + fclose(fp); + } + } + #endif + srand(seed); +} + +double randval(void) { + return rand() / (RAND_MAX + 1.0); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/random.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +random.o: random.c config.h random.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/random.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,7 @@ +#ifndef RANDOM_H_ +#define RANDOM_H_ + +void randseed(void); +double randval(void); + +#endif /* RANDOM_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/re.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2661 @@ +#include "config.h" +#include "IO.h" +#include "Str.h" +#include "hash.h" +#include "main_io.h" +#include "main_opt.h" +#include "re.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <limits.h> +#include <stddef.h> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +enum {CLASS_SIZE = UCHAR_MAX / CHAR_BIT + 1u}; + +static unsigned char dc_word[CLASS_SIZE]; +static unsigned char dc_alpha[CLASS_SIZE]; +static unsigned char dc_cntrl[CLASS_SIZE]; +static unsigned char dc_digit[CLASS_SIZE]; +static unsigned char dc_lower[CLASS_SIZE]; +static unsigned char dc_print[CLASS_SIZE]; +static unsigned char dc_space[CLASS_SIZE]; +static unsigned char dc_upper[CLASS_SIZE]; +static unsigned char dc_xdigit[CLASS_SIZE]; + +static void fill(unsigned char *v, int (*pred)(int)) { + unsigned char c; + + for (c = UCHAR_MAX; c; --c) { + v[c / CHAR_BIT] |= !!pred(c) << c % CHAR_BIT; + } + v[0] |= !!pred(0); +} + +static void nfill(unsigned char *v, int (*pred)(int)) { + unsigned char c; + + for (c = UCHAR_MAX; c; --c) { + v[c / CHAR_BIT] |= !pred(c) << c % CHAR_BIT; + } + v[0] |= !pred(0); +} + +ATTR_CONST +static int siword(int c) { + return c == '_' || isalnum(c); +} + +enum {MAGIC = 23}; + +static Hash rcache; +static String cached[MAGIC]; +static size_t cachfill, cachlast; + +static size_t hash(const void *s, size_t seed) { + return St_hash(s, seed); +} + +static int compar(const void *a, const void *b) { + return St_cmp(a, b); +} + +enum t_re_node { + RE_ALTER, + RE_ANYCH, + RE_AT_BOL, + RE_AT_BOS, + RE_AT_EOL, + RE_AT_EOS, + RE_AT_MATCH, + RE_AT_NOMATCH, + RE_AT_NWBOUND, + RE_AT_WBOUND, + RE_BACKCHECK, + RE_BACKREF, + RE_BEGIN_CAPTURE, + RE_CLASS, + RE_DEFCLASS, + RE_END_CAPTURE, + RE_INDEP, + RE_LITERAL, + RE_N_CLASS, + RE_N_DEFCLASS, + RE_PARTIAL, + RE_REP_FRUGAL, + RE_REP_GREEDY, + RE_SELECT, + RE_STUFF_FRUGAL, + RE_STUFF_GREEDY, + RE_XREP_FRUGAL, + RE_XREP_GREEDY +}; + +#define CMN_HDR enum t_re_node type; union my_node *next + +typedef union my_node { + struct { + CMN_HDR; + } x; + struct { + CMN_HDR; + union my_node *arg; + } alter; + struct { + CMN_HDR; + size_t n; + } backref; + struct { + CMN_HDR; + size_t n; + } capture; + struct { + CMN_HDR; + unsigned char vec[CLASS_SIZE]; + } class; + struct { + CMN_HDR; + unsigned char *vec; + } defclass; + struct { + CMN_HDR; + union my_node *arg; + } indep; + struct { + CMN_HDR; + unsigned char *buf; + size_t len; + } literal; + struct { + CMN_HDR; + union my_node *arg; + size_t min, max; + size_t n; + } rep; + struct { + CMN_HDR; + union my_node *arg; + union my_node *cond; + } select; +} re_node; + +#include "re_block.c.h" + +enum re_flags { + FL_NONE = 0, + FL_ANCHOR_START = 1 +}; + +struct cap_state { + size_t start, end, pending; +}; + +struct my_regex { + re_node *start; + size_t repets; + size_t *repbuf; + t_block alloc; + size_t captures; + struct cap_state *cap_ptr; + size_t refs; + enum re_flags flags; + size_t minlen; +}; + +static void delv(void *v) { + re_free(v); +} + +void re_init(void) { + fill(dc_word, siword); + fill(dc_alpha, isalpha); + fill(dc_cntrl, iscntrl); + fill(dc_digit, isdigit); + fill(dc_lower, islower); + fill(dc_print, isprint); + fill(dc_space, isspace); + fill(dc_upper, isupper); + fill(dc_xdigit, isxdigit); + + h_init(&rcache, hash, compar, NULL, delv); +} + +void re_end(void) { + h_end(&rcache); + while (cachfill) { + --cachfill; + St_clear(&cached[cachfill]); + } + cachlast = 0; +} + + +enum {ESCAPE = '!'}; +#define MEATCHARP(c) strchr("!|({<[]>})*+?:.'^$`", c) +#define ENDBRANCHP(c) strchr("|({<[", c) + +struct parse_context { + t_regex *base; + t_block *block; + const String *s; + size_t *p; +}; + +static void skipspace(const String *const s, size_t *const p) { +restart: + while (isspace(ST_INDEX(s, *p))) { + --*p; + } + if (ST_INDEX(s, *p) == ']' && ST_INDEX(s, *p - 1u) == '#') { + *p -= 2u; + while (ST_INDEX(s, *p) != EOF) { + if (ST_INDEX(s, *p) == '[') { + --*p; + goto restart; + } + if (ST_INDEX(s, *p) == ESCAPE && ST_INDEX(s, *p - 1u) != EOF) { + --*p; + } + --*p; + } + } +} + +#define PRAZ(name) static re_node *name(const struct parse_context *con, re_node *next, re_node *curolan_zebeth) +#define SNORK const String *const s = con->s; size_t *const p = con->p +#define CALL(name, nextn, glob) name(con, nextn, glob) +#define TAILC(name) return CALL(name, next, curolan_zebeth) + +PRAZ(quantifire); +PRAZ(branch); +PRAZ(alternation); + +PRAZ(atom) { + SNORK; + (void)curolan_zebeth; + + skipspace(s, p); + switch (ST_INDEX(s, *p)) { + case '(': + case '<': + case '{': + case '[': + case EOF: { + re_node *cur = bl_node(con->block); + cur->literal.type = RE_LITERAL; + cur->literal.next = next; + cur->literal.buf = NULL; + cur->literal.len = 0; + return cur; + } + + case ESCAPE: { + re_node *cur = bl_node(con->block); + --*p; + if (isdigit(ST_INDEX(s, *p))) { + do { + --*p; + } while (isdigit(ST_INDEX(s, *p))); + cur->backref.type = RE_BACKREF; + cur->backref.next = next; + cur->backref.n = strtoul(St_ptr(s) + *p + 1, NULL, 10); + } else if (isalpha(ST_INDEX(s, *p))) { + switch (ST_INDEX(s, *p)) { + case 'A': + cur->x.type = RE_AT_BOL; + cur->x.next = next; + --*p; + break; + case 'Z': + cur->x.type = RE_AT_EOL; + cur->x.next = next; + --*p; + break; + + case 'b': + cur->x.type = RE_AT_WBOUND; + cur->x.next = next; + --*p; + break; + case 'B': + cur->x.type = RE_AT_NWBOUND; + cur->x.next = next; + --*p; + break; + + case 'c': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_cntrl; + cur->defclass.next = next; + --*p; + break; + case 'C': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_cntrl; + cur->defclass.next = next; + --*p; + break; + + case 'd': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_digit; + cur->defclass.next = next; + --*p; + break; + case 'D': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_digit; + cur->defclass.next = next; + --*p; + break; + + case 'l': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_lower; + cur->defclass.next = next; + --*p; + break; + case 'L': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_lower; + cur->defclass.next = next; + --*p; + break; + + case 'p': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_print; + cur->defclass.next = next; + --*p; + break; + case 'P': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_print; + cur->defclass.next = next; + --*p; + break; + + case 'q': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_alpha; + cur->defclass.next = next; + --*p; + break; + case 'Q': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_alpha; + cur->defclass.next = next; + --*p; + break; + + case 's': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_space; + cur->defclass.next = next; + --*p; + break; + case 'S': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_space; + cur->defclass.next = next; + --*p; + break; + + case 'u': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_upper; + cur->defclass.next = next; + --*p; + break; + case 'U': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_upper; + cur->defclass.next = next; + --*p; + break; + + case 'w': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_word; + cur->defclass.next = next; + --*p; + break; + case 'W': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_word; + cur->defclass.next = next; + --*p; + break; + + case 'x': + cur->defclass.type = RE_DEFCLASS; + cur->defclass.vec = dc_xdigit; + cur->defclass.next = next; + --*p; + break; + case 'X': + cur->defclass.type = RE_N_DEFCLASS; + cur->defclass.vec = dc_xdigit; + cur->defclass.next = next; + --*p; + break; + + default: + goto default_escape; + } + + } else default_escape: { + cur->literal.type = RE_LITERAL; + cur->literal.next = next; + cur->literal.buf = bl_string(con->block, cur->literal.len = 1); + if (ST_INDEX(s, *p) == EOF) { + cur->literal.buf[0] = ESCAPE; + } else { + cur->literal.buf[0] = ST_INDEX(s, *p); + --*p; + } + } + return cur; + } + + case ')': { + re_node *cur; + --*p; + cur = CALL(alternation, next, next); + skipspace(s, p); + if (ST_INDEX(s, *p) == '(') { + --*p; + } + return cur; + } + + case ']': { + re_node *cur; + switch (ST_INDEX(s, *p - 1u)) { + case '&': + *p -= 2u; + cur = bl_node(con->block); + cur->indep.type = RE_AT_MATCH; + cur->indep.next = next; + cur->indep.arg = CALL(alternation, NULL, NULL); + break; + + case '^': + *p -= 2u; + cur = bl_node(con->block); + cur->indep.type = RE_AT_NOMATCH; + cur->indep.next = next; + cur->indep.arg = CALL(alternation, NULL, NULL); + break; + + case '?': + *p -= 2u; + cur = bl_node(con->block); + cur->select.type = RE_SELECT; + cur->select.cond = CALL(quantifire, NULL, NULL); + cur->select.arg = CALL(branch, next, next); + skipspace(s, p); + if (ST_INDEX(s, *p) == '|') { + --*p; + cur->select.next = CALL(alternation, next, next); + } else { + cur->select.next = next; + } + break; + + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + size_t i; + + for (i = *p - 2u; isdigit(ST_INDEX(s, i)); --i) + ; + if (ST_INDEX(s, i) != '[') { + goto std_atom; + } + cur = bl_node(con->block); + cur->backref.type = RE_BACKCHECK; + cur->backref.next = next; + cur->backref.n = strtoul(St_ptr(s) + i + 1u, NULL, 10); + *p = i - 1u; + + return cur; + } + + default: + goto std_atom; + } + + skipspace(s, p); + if (ST_INDEX(s, *p) == '[') { + --*p; + } + return cur; + } + + case '>': { + re_node *cur = bl_node(con->block); + --*p; + cur->indep.type = RE_INDEP; + cur->indep.next = next; + cur->indep.arg = CALL(alternation, NULL, NULL); + skipspace(s, p); + if (ST_INDEX(s, *p) == '<') { + --*p; + } + return cur; + } + + case '}': { + re_node *begin = bl_node(con->block); + re_node *end = bl_node(con->block); + --*p; + begin->capture.n = end->capture.n = con->base->captures++; + end->capture.type = RE_END_CAPTURE; + end->capture.next = next; + begin->capture.type = RE_BEGIN_CAPTURE; + begin->capture.next = CALL(alternation, end, end); + skipspace(s, p); + if (ST_INDEX(s, *p) == '{') { + --*p; + } + return begin; + } + + case '^': { + re_node *cur = bl_node(con->block); + cur->x.type = RE_AT_BOS; + cur->x.next = next; + --*p; + return cur; + } + + case '$': { + re_node *cur = bl_node(con->block); + cur->x.type = RE_AT_EOS; + cur->x.next = next; + --*p; + return cur; + } + + case '.': { + re_node *cur = bl_node(con->block); + cur->x.type = RE_ANYCH; + cur->x.next = next; + --*p; + return cur; + } + + case '`': { + String tmp; + int c; + re_node *cur = bl_node(con->block); + cur->literal.type = RE_PARTIAL; + cur->literal.next = next; + + --*p; + St_init(&tmp); + while ( + (c = ST_INDEX(s, *p)) != EOF && + c != '`' + ) { + --*p; + if (c == ESCAPE && ST_INDEX(s, *p) != EOF) { + c = ST_INDEX(s, *p); + --*p; + } + St_cat_c(&tmp, c); + } + if (c == '`') { + --*p; + } + St_reverse(&tmp); + + cur->literal.buf = bl_string(con->block, cur->literal.len = St_len(&tmp)); + memcpy(cur->literal.buf, St_ptr(&tmp), St_len(&tmp)); + St_clear(&tmp); + + return cur; + } + + case '\'': { + int c; + re_node *cur = bl_node(con->block); + cur->class.type = RE_CLASS; + cur->class.next = next; + memset(cur->class.vec, '\0', sizeof cur->class.vec); + for (--*p; (c = ST_INDEX(s, *p)) != EOF && c != '\''; --*p) { + if (c == ESCAPE) { + switch (c = ST_INDEX(s, *p - 1)) { + case EOF: + cur->class.vec[ESCAPE / CHAR_BIT] |= 1u << ESCAPE % CHAR_BIT; + break; + + case 'c': + fill(cur->class.vec, iscntrl); + --*p; + break; + case 'C': + nfill(cur->class.vec, iscntrl); + --*p; + break; + + case 'd': + fill(cur->class.vec, isdigit); + --*p; + break; + case 'D': + nfill(cur->class.vec, isdigit); + --*p; + break; + + case 'l': + fill(cur->class.vec, islower); + --*p; + break; + case 'L': + nfill(cur->class.vec, islower); + --*p; + break; + + case 'p': + fill(cur->class.vec, isprint); + --*p; + break; + case 'P': + nfill(cur->class.vec, isprint); + --*p; + break; + + case 'q': + fill(cur->class.vec, isalpha); + --*p; + break; + case 'Q': + nfill(cur->class.vec, isalpha); + --*p; + break; + + case 's': + fill(cur->class.vec, isspace); + --*p; + break; + case 'S': + nfill(cur->class.vec, isspace); + --*p; + break; + + case 'u': + fill(cur->class.vec, isupper); + --*p; + break; + case 'U': + nfill(cur->class.vec, isupper); + --*p; + break; + + case 'w': + fill(cur->class.vec, siword); + --*p; + break; + case 'W': + nfill(cur->class.vec, siword); + --*p; + break; + + case 'x': + fill(cur->class.vec, isxdigit); + --*p; + break; + case 'X': + nfill(cur->class.vec, isxdigit); + --*p; + break; + + default: + cur->class.vec[c / CHAR_BIT] |= 1u << c % CHAR_BIT; + --*p; + break; + } + } else { + int b; + if (ST_INDEX(s, *p - 1) == '-' && (b = ST_INDEX(s, *p - 2)) != EOF) { + if (b == ESCAPE && (b = ST_INDEX(s, *p - 3)) == EOF) { + b = ESCAPE; + } + if (b > c) { + goto normal_char; + } + for (; b < c; ++b) { + cur->class.vec[b / CHAR_BIT] |= 1u << b % CHAR_BIT; + } + cur->class.vec[b / CHAR_BIT] |= 1u << b % CHAR_BIT; + *p -= 2; + if (ST_INDEX(s, *p) == ESCAPE && ST_INDEX(s, *p - 1) != EOF) { + --*p; + } + } else if (ST_INDEX(s, *p) == ']' && *p >= 8 && ST_INDEX(s, *p - 1) == ':') { + +#define CXCLASS_CHECK(n, t, f, o, b) if (1) { \ + if (memcmp(St_ptr(s) + *p - (n), (t), (n) - 1) != 0) { \ + goto normal_char; \ + } \ + (b)(cur->class.vec, (f)); \ + *p -= (o); \ + break; \ +} else (void)0 + +#define CCLASS_CHECK(t, f, o) CXCLASS_CHECK(sizeof (t), t, f, o, fill) +#define CNCLASS_CHECK(t, f, o) CXCLASS_CHECK(sizeof (t), t, f, o, nfill) + + if (ST_INDEX(s, *p - 8) == '[' && ST_INDEX(s, *p - 7) == ':') { + switch (ST_INDEX(s, *p - 6)) { + case 'a': + if (ST_INDEX(s, *p - 5) != 'l') { + goto normal_char; + } + switch (ST_INDEX(s, *p - 4)) { + case 'n': CCLASS_CHECK("um", isalnum, 8); + case 'p': CCLASS_CHECK("ha", isalpha, 8); + default: goto normal_char; + } + break; + + case 'c': CCLASS_CHECK("ntrl", iscntrl, 8); + case 'd': CCLASS_CHECK("igit", isdigit, 8); + case 'g': CCLASS_CHECK("raph", isgraph, 8); + case 'l': CCLASS_CHECK("ower", islower, 8); + + case 'p': + switch (ST_INDEX(s, *p - 5)) { + case 'r': CCLASS_CHECK("int", isprint, 8); + case 'u': CCLASS_CHECK("nct", ispunct, 8); + default: goto normal_char; + } + break; + + case 's': CCLASS_CHECK("pace", isspace, 8); + case 'u': CCLASS_CHECK("pper", isupper, 8); + default: goto normal_char; + } + } else if (*p >= 9 && ST_INDEX(s, *p - 9) == '[' && ST_INDEX(s, *p - 8) == ':') { + switch (ST_INDEX(s, *p - 7)) { + case 'x': + CCLASS_CHECK("digit", isxdigit, 9); + + case '^': + switch (ST_INDEX(s, *p - 6)) { + case 'a': + if (ST_INDEX(s, *p - 5) != 'l') { + goto normal_char; + } + switch (ST_INDEX(s, *p - 4)) { + case 'n': CNCLASS_CHECK("um", isalnum, 9); + case 'p': CNCLASS_CHECK("ha", isalpha, 9); + default: goto normal_char; + } + break; + + case 'c': CNCLASS_CHECK("ntrl", iscntrl, 9); + case 'd': CNCLASS_CHECK("igit", isdigit, 9); + case 'g': CNCLASS_CHECK("raph", isgraph, 9); + case 'l': CNCLASS_CHECK("ower", islower, 9); + + case 'p': + switch (ST_INDEX(s, *p - 5)) { + case 'r': CNCLASS_CHECK("int", isprint, 9); + case 'u': CNCLASS_CHECK("nct", ispunct, 9); + default: goto normal_char; + } + break; + + case 's': CNCLASS_CHECK("pace", isspace, 9); + case 'u': CNCLASS_CHECK("pper", isupper, 9); + default: goto normal_char; + } + break; + + default: goto normal_char; + } + } else if (*p >= 10 && memcmp(St_ptr(s) + *p - 10, "[:^xdigit", 9) == 0) { + nfill(cur->class.vec, isxdigit); + *p -= 10; + } else { + goto normal_char; + } + } else if (ST_INDEX(s, *p) == '^' && ((b = ST_INDEX(s, *p - 1) == '\'') || b == EOF)) { + cur->class.type = RE_N_CLASS; + } else normal_char: { + cur->class.vec[c / CHAR_BIT] |= 1u << c % CHAR_BIT; + } + } + } + if (c == '\'') { + --*p; + } + + if (cur->class.type == RE_CLASS) { + size_t i; + for (i = 0; i < CLASS_SIZE; ++i) { + if (cur->class.vec[i] != (unsigned char)~0u) { + return cur; + } + } + cur->x.type = RE_ANYCH; + } else { + size_t i; + assert(cur->class.type == RE_N_CLASS); + for (i = 0; i < CLASS_SIZE; ++i) { + if (cur->class.vec[i] != 0) { + return cur; + } + } + cur->x.type = RE_ANYCH; + } + + return cur; + } + +std_atom: + default: { + re_node *cur = bl_node(con->block); + cur->literal.type = RE_LITERAL; + + /*XXX?*/ + if (next && next->x.type == RE_LITERAL) { + if (next->literal.len) { + cur->literal.buf = bl_string(con->block, cur->literal.len = 1u + next->literal.len); + memcpy(cur->literal.buf + 1, next->literal.buf, next->literal.len); + } + cur->literal.next = next->literal.next; + } else { + cur->literal.next = next; + cur->literal.buf = bl_string(con->block, cur->literal.len = 1); + } + + cur->literal.buf[0] = ST_INDEX(s, *p); + --*p; + return cur; + } + } +} + +PRAZ(literal) { + SNORK; + int c; + String tmp; + re_node *cur; + + skipspace(s, p); + if ((ST_INDEX(s, *p) != ESCAPE || isalnum(ST_INDEX(s, *p - 1))) && MEATCHARP(ST_INDEX(s, *p))) { + TAILC(atom); + } + + cur = bl_node(con->block); + cur->literal.type = RE_LITERAL; + cur->literal.next = next; + + St_init(&tmp); + while ( + (c = ST_INDEX(s, *p)) != EOF && + ( + !MEATCHARP(c) || + (c == ESCAPE && !isalnum(ST_INDEX(s, *p - 1))) + ) + ) { + --*p; + if (c == ESCAPE && ST_INDEX(s, *p) != EOF) { + c = ST_INDEX(s, *p); + --*p; + } + St_cat_c(&tmp, c); + skipspace(s, p); + } + St_reverse(&tmp); + + if (next && next->x.type == RE_LITERAL) { + if (next->literal.len) { + St_cat_m(&tmp, next->literal.buf, next->literal.len); + } + cur->literal.next = next->literal.next; + } + + cur->literal.buf = bl_string(con->block, cur->literal.len = St_len(&tmp)); + memcpy(cur->literal.buf, St_ptr(&tmp), St_len(&tmp)); + St_clear(&tmp); + + return cur; +} + +#define RETURN_REP(lo, hi, grdy) \ +do { \ + re_node *cur = bl_node(con->block); \ + cur->rep.type = (grdy); \ + cur->rep.next = next; \ + cur->rep.min = (lo); \ + cur->rep.max = (hi); \ + cur->rep.n = con->base->repets++; \ + cur->rep.arg = CALL(atom, cur, NULL); \ + return cur; \ +} while (0) + +#define STD_REP_CASE(lo, hi, grdy) \ +do { \ + --*p; \ + RETURN_REP(lo, hi, grdy); \ +} while (0) + +#define CUSTOM_REP_CASE(off, grdy, mismatch) \ +do { \ + size_t from, to; \ + to = *p - 1 - (off); \ + while (isdigit(ST_INDEX(s, to))) { \ + --to; \ + } \ + if (ST_INDEX(s, to) == ':') { \ + *p = to - 1; \ + to = ST_INDEX(s, to + 1) == ':' ? (size_t)-1 : strtoul(St_ptr(s) + to + 1, NULL, 10); \ + from = to; \ + } else { \ + if (ST_INDEX(s, to) != ',') { \ + mismatch; \ + } \ + from = to - 1; \ + if (!isdigit(ST_INDEX(s, from))) { \ + mismatch; \ + } \ + do { \ + --from; \ + } while (isdigit(ST_INDEX(s, from))); \ + if (ST_INDEX(s, from) != ':') { \ + mismatch; \ + } \ + *p = from - 1; \ + from = strtoul(St_ptr(s) + from + 1, NULL, 10); \ + to = ST_INDEX(s, to + 1) == ':' ? (size_t)-1 : strtoul(St_ptr(s) + to + 1, NULL, 10); \ + } \ + if (to == 1) { \ + if (from == 1) { \ + TAILC(atom); \ + } \ + if (from == 0) { \ + re_node *cur = bl_node(con->block); \ + cur->alter.type = RE_ALTER; \ + if ((grdy) == RE_REP_GREEDY) { \ + cur->alter.next = next; \ + cur->alter.arg = CALL(atom, next, NULL); \ + } else { \ + cur->alter.arg = next; \ + cur->alter.next = CALL(atom, next, NULL); \ + } \ + return cur; \ + } \ + } \ + RETURN_REP(from, to, grdy); \ +} while (0) + +PRAZ(quantifire) { + SNORK; + + skipspace(s, p); + switch (ST_INDEX(s, *p)) { + case EOF: return next; + + case '?': + switch (ST_INDEX(s, *p - 1)) { + case ':': CUSTOM_REP_CASE(1, RE_REP_FRUGAL, goto hook); + case '*': --*p; STD_REP_CASE(0, -1, RE_REP_FRUGAL); + case '+': --*p; STD_REP_CASE(1, -1, RE_REP_FRUGAL); + + case '?': { + re_node *cur = bl_node(con->block); + *p -= 2; + cur->alter.type = RE_ALTER; + cur->alter.next = CALL(atom, next, NULL); + cur->alter.arg = next; + return cur; + } + +hook: + default: { + re_node *cur = bl_node(con->block); + --*p; + cur->alter.type = RE_ALTER; + cur->alter.next = next; + cur->alter.arg = CALL(atom, next, NULL); + return cur; + } + } + + case ':': CUSTOM_REP_CASE(0, RE_REP_GREEDY, goto noquanti); + case '*': STD_REP_CASE(0, -1, RE_REP_GREEDY); + case '+': STD_REP_CASE(1, -1, RE_REP_GREEDY); + +noquanti: + default: TAILC(literal); + } +} + +PRAZ(branch) { + SNORK; + skipspace(s, p); + while (ST_INDEX(s, *p) != EOF && !ENDBRANCHP(ST_INDEX(s, *p))) { + next = CALL(quantifire, next, curolan_zebeth); + skipspace(s, p); + } + return next; +} + +PRAZ(alternation) { + SNORK; + re_node *cur; + + skipspace(s, p); + if (ST_INDEX(s, *p) == EOF) { + return next; + } + + next = CALL(branch, next, curolan_zebeth); + skipspace(s, p); + if (ST_INDEX(s, *p) != '|') { + return next; + } + + --*p; + cur = bl_node(con->block); + cur->alter.type = RE_ALTER; + cur->alter.next = next; + cur->alter.arg = CALL(alternation, curolan_zebeth, curolan_zebeth); + return cur; +} + +ATTR_CONST +static size_t minimum(const size_t a, const size_t b) { + return a < b ? a : b; +} + +ATTR_CONST +static size_t maximum(const size_t a, const size_t b) { + return a > b ? a : b; +} + +ATTR_PURE +static size_t subminlen(const re_node *node, const re_node *end, size_t start) { + if (!node || node == end) { + return start; + } + + switch (node->x.type) { + case RE_ALTER: + return minimum( + subminlen(node->alter.arg, end, start), + subminlen(node->alter.next, end, start) + ); + + case RE_ANYCH: + case RE_CLASS: + case RE_DEFCLASS: + case RE_N_CLASS: + case RE_N_DEFCLASS: + return subminlen(node->x.next, end, start + 1u); + + case RE_AT_BOL: + case RE_AT_BOS: + case RE_AT_EOL: + case RE_AT_EOS: + case RE_AT_NWBOUND: + case RE_AT_WBOUND: + case RE_BACKCHECK: + case RE_BACKREF: + case RE_BEGIN_CAPTURE: + case RE_END_CAPTURE: + case RE_PARTIAL: + case RE_STUFF_FRUGAL: + case RE_STUFF_GREEDY: + return subminlen(node->x.next, end, start); + + case RE_AT_MATCH: + return maximum( + subminlen(node->indep.arg, end, start), + subminlen(node->indep.next, end, start) + ); + + case RE_AT_NOMATCH: + return subminlen(node->indep.next, end, start); + + case RE_INDEP: + return subminlen(node->indep.next, end, start + subminlen(node->indep.arg, NULL, 0)); + + case RE_LITERAL: + return subminlen(node->literal.next, end, start + node->literal.len); + + case RE_SELECT: + return minimum( + subminlen(node->select.cond, end, start) + subminlen(node->select.arg, end, start), + subminlen(node->select.next, end, start) + ); + + case RE_REP_FRUGAL: + case RE_REP_GREEDY: + if (node->rep.min == 0) { + return subminlen(node->rep.next, end, start); + } + return subminlen(node->rep.next, end, start + node->rep.min * subminlen(node->rep.arg, node, 0)); + + case RE_XREP_FRUGAL: + case RE_XREP_GREEDY: + if (node->rep.min == 0) { + return subminlen(node->rep.next, end, start); + } + return subminlen(node->rep.next, end, start + node->rep.min * subminlen(node->rep.arg, NULL, 0)); + } + + NOTREACHED; +} + +ATTR_PURE +static size_t minlen(const re_node *node) { + return subminlen(node, NULL, 0); +} + +static void reinit(t_regex *re) { + const struct cap_state null = { -1, -1, -1 }; + size_t i; + for (i = 0; i < re->captures; ++i) { + re->cap_ptr[i] = null; + } +} + +static re_node **notcomplex(re_node **node, const re_node *end) { + assert(*node != NULL); + + if (*node == end) { + return node; + } + + switch ((*node)->x.type) { + case RE_ALTER: + case RE_AT_MATCH: + case RE_AT_NOMATCH: + case RE_BACKCHECK: + case RE_BACKREF: + case RE_BEGIN_CAPTURE: + case RE_END_CAPTURE: + case RE_INDEP: + case RE_PARTIAL: + case RE_REP_FRUGAL: + case RE_REP_GREEDY: + case RE_SELECT: + case RE_STUFF_FRUGAL: + case RE_STUFF_GREEDY: + return NULL; + + case RE_XREP_FRUGAL: + case RE_XREP_GREEDY: + if ((*node)->rep.min == (*node)->rep.max) { + return notcomplex(&(*node)->rep.next, end); + } + return NULL; + + case RE_ANYCH: + case RE_AT_BOL: + case RE_AT_BOS: + case RE_AT_EOL: + case RE_AT_EOS: + case RE_AT_NWBOUND: + case RE_AT_WBOUND: + case RE_CLASS: + case RE_DEFCLASS: + case RE_LITERAL: + case RE_N_CLASS: + case RE_N_DEFCLASS: + return notcomplex(&(*node)->x.next, end); + } + + NOTREACHED; +} + +static void trysimpl(re_node *node) { + assert(node->x.type == RE_REP_FRUGAL || node->x.type == RE_REP_GREEDY); + + { + re_node **const tmp = notcomplex(&node->rep.arg, node); + if (!tmp) { + return; + } + *tmp = NULL; + } + + switch (node->rep.type) { + case RE_REP_FRUGAL: + if ( + node->rep.arg->x.type == RE_ANYCH && + node->rep.arg->x.next == NULL && + node->rep.max == (size_t)-1 + ) { + if (node->rep.min == 0) { + node->x.type = RE_STUFF_FRUGAL; + break; + } + if (node->rep.min == 1) { + node->rep.arg->x.next = node->x.next; + node->rep.arg->x.type = RE_STUFF_FRUGAL; + node->x.next = node->rep.arg; + node->x.type = RE_ANYCH; + break; + } + } + + node->rep.n = minlen(node->rep.arg); + node->rep.type = RE_XREP_FRUGAL; + break; + + case RE_REP_GREEDY: + if ( + node->rep.arg->x.type == RE_ANYCH && + node->rep.arg->x.next == NULL && + node->rep.max == (size_t)-1 + ) { + if (node->rep.min == 0) { + node->x.type = RE_STUFF_GREEDY; + break; + } + if (node->rep.min == 1) { + node->rep.arg->x.next = node->x.next; + node->rep.arg->x.type = RE_STUFF_GREEDY; + node->x.next = node->rep.arg; + node->x.type = RE_ANYCH; + break; + } + } + + node->rep.n = minlen(node->rep.arg); + node->rep.type = RE_XREP_GREEDY; + break; + + default: + NOTREACHED; + } + +} + +static void simplerep(re_node *node, const re_node *const end) { + if (!node || node == end) { + return; + } + + switch (node->x.type) { + case RE_ALTER: + simplerep(node->alter.arg, end); + simplerep(node->alter.next, end); + return; + + case RE_AT_MATCH: + case RE_AT_NOMATCH: + case RE_INDEP: + simplerep(node->indep.arg, end); + simplerep(node->indep.next, end); + return; + + case RE_ANYCH: + case RE_AT_BOL: + case RE_AT_BOS: + case RE_AT_EOL: + case RE_AT_EOS: + case RE_AT_NWBOUND: + case RE_AT_WBOUND: + case RE_BACKCHECK: + case RE_BACKREF: + case RE_BEGIN_CAPTURE: + case RE_CLASS: + case RE_DEFCLASS: + case RE_END_CAPTURE: + case RE_LITERAL: + case RE_N_CLASS: + case RE_N_DEFCLASS: + case RE_PARTIAL: + simplerep(node->x.next, end); + return; + + case RE_REP_FRUGAL: + case RE_REP_GREEDY: + simplerep(node->rep.next, end); + simplerep(node->rep.arg, node); + trysimpl(node); + return; + + case RE_SELECT: + simplerep(node->select.cond, end); + simplerep(node->select.arg, end); + simplerep(node->select.next, end); + return; + + case RE_STUFF_FRUGAL: + case RE_STUFF_GREEDY: + case RE_XREP_FRUGAL: + case RE_XREP_GREEDY: + return; + } + + NOTREACHED; +} + +ATTR_PURE +static int anchorbegp(const re_node *node) { + return + node && + ( + node->x.type == RE_AT_BOS || + node->x.type == RE_STUFF_FRUGAL || + node->x.type == RE_STUFF_GREEDY || + ( + node->x.type == RE_ALTER && + anchorbegp(node->alter.arg) && + anchorbegp(node->alter.next) + ) || + ( + node->x.type == RE_INDEP && + anchorbegp(node->indep.arg) + ) || + ( + node->x.type == RE_AT_MATCH && + ( + anchorbegp(node->indep.arg) || + anchorbegp(node->indep.next) + ) + ) || + ( + ( + node->x.type == RE_AT_NOMATCH || + node->x.type == RE_AT_BOL || + node->x.type == RE_AT_EOL || + node->x.type == RE_AT_EOS || + node->x.type == RE_AT_NWBOUND || + node->x.type == RE_AT_WBOUND || + node->x.type == RE_BEGIN_CAPTURE || + node->x.type == RE_BACKCHECK + ) && + anchorbegp(node->x.next) + ) + ) + ; +} + +static void dostuff(t_regex *re) { + simplerep(re->start, NULL); + + if (!re->start || anchorbegp(re->start)) { + re->flags |= FL_ANCHOR_START; + } +} + +t_regex *re_compile(const String *s) { + size_t p; + struct parse_context dcon; + t_regex *re; + void *pre; + + if (h_get(&rcache, s, &pre) == H_OK) { + re = pre; + ++re->refs; + return re; + } + + re = xmalloc(1, sizeof *re); + re->flags = FL_NONE; + re->refs = 0; + re->repets = 0; + bl_init(&re->alloc); + re->cap_ptr = NULL; + re->captures = 0; + dcon.base = re; + dcon.block = &re->alloc; + dcon.s = s; + p = St_len(s) - 1; + dcon.p = &p; + + re->start = alternation(&dcon, NULL, NULL); + + if (re->captures) { + re->cap_ptr = xmalloc(re->captures, sizeof *re->cap_ptr); + reinit(re); + } + + dostuff(re); + re->minlen = minlen(re->start); + re->repbuf = xmalloc(re->repets, sizeof *re->repbuf); + + if (cachfill < sizeof cached / sizeof cached[0]) { + St_init(&cached[cachfill]); + St_cpy(&cached[cachfill], s); + ++re->refs; + h_put(&rcache, &cached[cachfill], re, 1); + ++cachfill; + } else { + h_del(&rcache, &cached[cachlast]); + St_cpy(&cached[cachlast], s); + ++re->refs; + h_put(&rcache, &cached[cachlast], re, 1); + cachlast = (cachlast + 1u) % (sizeof cached / sizeof cached[0]); + } + + if (Opt.debug & DBG_REGEX) { + io_write_s(Err, "Compiled "); + re_dump(re, io_fp(Err)); + } + + return re; +} + +t_regex *re_dup(t_regex *re) { + ++re->refs; + return re; +} + +void re_free(t_regex *re) { + if (re->refs) { + --re->refs; + return; + } + bl_free(&re->alloc); + xfree(re->repbuf); + xfree(re->cap_ptr); + xfree(re); +} + +ATTR_PURE +static int match_class(unsigned char c, const unsigned char *vec) { + return vec[c / CHAR_BIT] & 1u << c % CHAR_BIT; +} + +static void *mem_dup(const void *p, size_t n, size_t m) { + void *q = xmalloc(n, m); + memcpy(q, p, n * m); + return q; +} + +#define NO_MATCH ((size_t)-1) + +#define Mmatch0(Xmatch, Xindex) \ + size_t tmp; \ + \ + if (!node) { \ + return o; \ + } \ + \ + switch (node->x.type) { \ + case RE_ALTER: \ + if ((tmp = Xmatch(base, node->alter.arg, s, o)) == NO_MATCH) { \ + return Xmatch(base, node->alter.next, s, o); \ + } \ + return tmp; \ + \ + case RE_ANYCH: \ + if (Xindex(s, o) != EOF) { \ + return Xmatch(base, node->x.next, s, o + 1u); \ + } \ + return NO_MATCH; \ + \ + case RE_AT_BOL: \ + if (o == 0 || Xindex(s, o - 1u) == '\n') { \ + return Xmatch(base, node->x.next, s, o); \ + } \ + return NO_MATCH; \ + \ + case RE_AT_BOS: \ + if (o == 0) { \ + return Xmatch(base, node->x.next, s, o); \ + } \ + return NO_MATCH; \ + \ + case RE_AT_EOL: \ + if ( \ + Xindex(s, o) == '\n' || \ + ( \ + o && Xindex(s, o) == EOF && Xindex(s, o - 1u) != '\n' \ + ) \ + ) { \ + return Xmatch(base, node->x.next, s, o); \ + } \ + return NO_MATCH; \ + \ + case RE_AT_EOS: \ + if (Xindex(s, o) == EOF) { \ + return Xmatch(base, node->x.next, s, o); \ + } \ + return NO_MATCH; \ + \ + case RE_AT_MATCH: { \ + struct cap_state *prev = mem_dup(base->cap_ptr, base->captures, sizeof *base->cap_ptr); \ + tmp = Xmatch(base, node->indep.arg, s, o); \ + if (tmp != NO_MATCH) { \ + tmp = Xmatch(base, node->indep.next, s, o); \ + if (tmp == NO_MATCH) { \ + memcpy(base->cap_ptr, prev, base->captures * sizeof *base->cap_ptr); \ + } \ + } \ + xfree(prev); \ + return tmp; \ + } \ + \ + case RE_AT_NOMATCH: { \ + struct cap_state *prev = mem_dup(base->cap_ptr, base->captures, sizeof *base->cap_ptr); \ + tmp = Xmatch(base, node->indep.arg, s, o); \ + if (tmp == NO_MATCH) { \ + tmp = Xmatch(base, node->indep.next, s, o); \ + } else { \ + memcpy(base->cap_ptr, prev, base->captures * sizeof *base->cap_ptr); \ + tmp = NO_MATCH; \ + } \ + xfree(prev); \ + return tmp; \ + } \ + \ + case RE_AT_NWBOUND: \ + if (siword(Xindex(s, o - 1u)) == siword(Xindex(s, o))) { \ + return Xmatch(base, node->x.next, s, o); \ + } \ + return NO_MATCH; \ + \ + case RE_AT_WBOUND: \ + if (siword(Xindex(s, o - 1u)) != siword(Xindex(s, o))) { \ + return Xmatch(base, node->x.next, s, o); \ + } \ + return NO_MATCH; \ + \ + case RE_BACKCHECK: \ + if ( \ + node->backref.n < base->captures && \ + base->cap_ptr[node->backref.n].start + 1u && \ + base->cap_ptr[node->backref.n].end + 1u && \ + base->cap_ptr[node->backref.n].end >= base->cap_ptr[node->backref.n].start \ + ) { \ + return Xmatch(base, node->backref.next, s, o); \ + } \ + return NO_MATCH + + +#define Mmatch1(Xmatch, Xindex) \ + case RE_BEGIN_CAPTURE: { \ + const size_t prev = base->cap_ptr[node->capture.n].pending; \ + base->cap_ptr[node->capture.n].pending = o; \ + if ((tmp = Xmatch(base, node->capture.next, s, o)) == NO_MATCH) { \ + base->cap_ptr[node->capture.n].pending = prev; \ + } \ + return tmp; \ + } \ + \ + case RE_CLASS: \ + if ( \ + Xindex(s, o) != EOF && \ + match_class(Xindex(s, o), node->class.vec) \ + ) { \ + return Xmatch(base, node->class.next, s, o + 1u); \ + } \ + return NO_MATCH; \ + \ + case RE_DEFCLASS: \ + if ( \ + Xindex(s, o) != EOF && \ + match_class(Xindex(s, o), node->defclass.vec) \ + ) { \ + return Xmatch(base, node->defclass.next, s, o + 1u); \ + } \ + return NO_MATCH; \ + \ + case RE_END_CAPTURE: { \ + const size_t prevbeg = base->cap_ptr[node->capture.n].start; \ + const size_t prevend = base->cap_ptr[node->capture.n].end; \ + if (base->cap_ptr[node->capture.n].pending + 1u == 0u) { \ + return NO_MATCH; \ + } \ + \ + base->cap_ptr[node->capture.n].end = o; \ + base->cap_ptr[node->capture.n].start = base->cap_ptr[node->capture.n].pending; \ + if ((tmp = Xmatch(base, node->capture.next, s, o)) == NO_MATCH) { \ + base->cap_ptr[node->capture.n].end = prevend; \ + base->cap_ptr[node->capture.n].start = prevbeg; \ + } \ + return tmp; \ + } \ + \ + case RE_INDEP: { \ + struct cap_state *prev = mem_dup(base->cap_ptr, base->captures, sizeof *base->cap_ptr); \ + if ((tmp = Xmatch(base, node->indep.arg, s, o)) != NO_MATCH) { \ + tmp = Xmatch(base, node->indep.next, s, tmp); \ + if (tmp == NO_MATCH) { \ + memcpy(base->cap_ptr, prev, base->captures * sizeof *base->cap_ptr); \ + } \ + } \ + xfree(prev); \ + return tmp; \ + } \ + \ + case RE_N_CLASS: \ + if ( \ + Xindex(s, o) != EOF && \ + !match_class(Xindex(s, o), node->class.vec) \ + ) { \ + return Xmatch(base, node->class.next, s, o + 1u); \ + } \ + return NO_MATCH; \ + \ + case RE_N_DEFCLASS: \ + if ( \ + Xindex(s, o) != EOF && \ + !match_class(Xindex(s, o), node->defclass.vec) \ + ) { \ + return Xmatch(base, node->defclass.next, s, o + 1u); \ + } \ + return NO_MATCH; \ + \ + case RE_PARTIAL: { \ + size_t n; \ + for (n = 0; n < node->literal.len; ++n) { \ + if (node->literal.buf[n] != Xindex(s, o + n)) { \ + break; \ + } \ + } \ + for (; n; --n) { \ + if ((tmp = Xmatch(base, node->literal.next, s, o + n)) != NO_MATCH) { \ + return tmp; \ + } \ + } \ + return Xmatch(base, node->literal.next, s, o); \ + } \ + \ + case RE_SELECT: { \ + struct cap_state *prev = mem_dup(base->cap_ptr, base->captures, sizeof *base->cap_ptr); \ + if ((tmp = Xmatch(base, node->select.cond, s, o)) != NO_MATCH) { \ + tmp = Xmatch(base, node->select.arg, s, tmp); \ + if (tmp == NO_MATCH) { \ + memcpy(base->cap_ptr, prev, base->captures * sizeof *base->cap_ptr); \ + } \ + } else { \ + tmp = Xmatch(base, node->select.next, s, o); \ + } \ + xfree(prev); \ + return tmp; \ + } \ + \ + case RE_REP_FRUGAL: \ + if (base->repbuf[node->rep.n] >= node->rep.max) { \ + const size_t n = base->repbuf[node->rep.n]; \ + \ + base->repbuf[node->rep.n] = 0; \ + tmp = Xmatch(base, node->rep.next, s, o); \ + base->repbuf[node->rep.n] = n; \ + return tmp; \ + } else if (base->repbuf[node->rep.n] >= node->rep.min) { \ + const size_t n = base->repbuf[node->rep.n]; \ + \ + base->repbuf[node->rep.n] = 0; \ + if ((tmp = Xmatch(base, node->rep.next, s, o)) != NO_MATCH) { \ + base->repbuf[node->rep.n] = n; \ + return tmp; \ + } \ + base->repbuf[node->rep.n] = n + 1u; \ + tmp = Xmatch(base, node->rep.arg, s, o); \ + --base->repbuf[node->rep.n]; \ + return tmp; \ + } else { \ + ++base->repbuf[node->rep.n]; \ + tmp = Xmatch(base, node->rep.arg, s, o); \ + --base->repbuf[node->rep.n]; \ + return tmp; \ + } \ + \ + case RE_REP_GREEDY: \ + if (base->repbuf[node->rep.n] >= node->rep.max) { \ + const size_t n = base->repbuf[node->rep.n]; \ + \ + base->repbuf[node->rep.n] = 0; \ + tmp = Xmatch(base, node->rep.next, s, o); \ + base->repbuf[node->rep.n] = n; \ + return tmp; \ + } else if (base->repbuf[node->rep.n] >= node->rep.min) { \ + const size_t n = base->repbuf[node->rep.n]; \ + \ + ++base->repbuf[node->rep.n]; \ + if ((tmp = Xmatch(base, node->rep.arg, s, o)) != NO_MATCH) { \ + --base->repbuf[node->rep.n]; \ + return tmp; \ + } \ + base->repbuf[node->rep.n] = 0; \ + tmp = Xmatch(base, node->rep.next, s, o); \ + base->repbuf[node->rep.n] = n; \ + return tmp; \ + } else { \ + ++base->repbuf[node->rep.n]; \ + tmp = Xmatch(base, node->rep.arg, s, o); \ + --base->repbuf[node->rep.n]; \ + return tmp; \ + } \ + \ + case RE_XREP_FRUGAL: { \ + size_t n; \ + \ + for (n = 0; n < node->rep.min; ++n) { \ + if ((tmp = Xmatch(base, node->rep.arg, s, o)) == NO_MATCH) { \ + return NO_MATCH; \ + } \ + o = tmp; \ + } \ + \ + for (; n < node->rep.max; ++n) { \ + if ((tmp = Xmatch(base, node->rep.next, s, o)) != NO_MATCH) { \ + return tmp; \ + } \ + if ((tmp = Xmatch(base, node->rep.arg, s, o)) == NO_MATCH) { \ + return NO_MATCH; \ + } \ + o = tmp; \ + } \ + return Xmatch(base, node->rep.next, s, o); \ + } \ + \ + case RE_XREP_GREEDY: { \ + size_t n; \ + \ + for (n = 0; n < node->rep.min; ++n) { \ + if ((tmp = Xmatch(base, node->rep.arg, s, o)) == NO_MATCH) { \ + return NO_MATCH; \ + } \ + o = tmp; \ + } \ + \ + for (; n < node->rep.max; ++n) { \ + if ((tmp = Xmatch(base, node->rep.arg, s, o)) == NO_MATCH) { \ + break; \ + } \ + o = tmp; \ + } \ + \ + for (; n > node->rep.min; --n) { \ + if ((tmp = Xmatch(base, node->rep.next, s, o)) != NO_MATCH) { \ + return tmp; \ + } \ + o -= node->rep.n; \ + } \ + \ + return Xmatch(base, node->rep.next, s, o); \ + } \ + } \ + \ + NOTREACHED + + +static size_t match(const t_regex *base, const re_node *node, const String *s, size_t o) { + + Mmatch0(match, ST_INDEX); + + case RE_BACKREF: + if ( + node->backref.n < base->captures && + base->cap_ptr[node->backref.n].start + 1u && + base->cap_ptr[node->backref.n].end + 1u && + base->cap_ptr[node->backref.n].end >= base->cap_ptr[node->backref.n].start && + ( + base->cap_ptr[node->backref.n].end - base->cap_ptr[node->backref.n].start <= St_len(s) - o && + memcmp( + St_ptr(s) + base->cap_ptr[node->backref.n].start, + St_ptr(s) + o, + base->cap_ptr[node->backref.n].end - base->cap_ptr[node->backref.n].start + ) == 0 + ) + ) { + return match(base, node->backref.next, s, o + base->cap_ptr[node->backref.n].end - base->cap_ptr[node->backref.n].start); + } + return NO_MATCH; + + + case RE_LITERAL: + if ( + node->literal.len == 0 || + ( + node->literal.len <= St_len(s) - o && + memcmp(node->literal.buf, St_ptr(s) + o, node->literal.len) == 0 + ) + ) { + return match(base, node->literal.next, s, o + node->literal.len); + } + return NO_MATCH; + + case RE_STUFF_FRUGAL: + if (!node->x.next) { + return o; + } + + if (node->x.next->x.type == RE_LITERAL && node->x.next->literal.len) { + for ( + o = St_stro_m(s, o, node->x.next->literal.buf, node->x.next->literal.len); + o + 1u; + o = St_stro_m(s, o + 1u, node->x.next->literal.buf, node->x.next->literal.len) + ) { + if ((tmp = match(base, node->x.next->literal.next, s, o + node->x.next->literal.len)) != NO_MATCH) { + return tmp; + } + } + return NO_MATCH; + } + + for (; o <= St_len(s); ++o) { + if ((tmp = match(base, node->x.next, s, o)) != NO_MATCH) { + return tmp; + } + } + return NO_MATCH; + + case RE_STUFF_GREEDY: { + size_t n; + + if (!node->x.next) { + return St_len(s); + } + + if (node->x.next->x.type == RE_LITERAL && node->x.next->literal.len) { + for ( + n = St_rstr_m(s, node->x.next->literal.buf, node->x.next->literal.len); + n > o && n + 1u; + n = St_rstro_m(s, n - 1u, node->x.next->literal.buf, node->x.next->literal.len) + ) { + if ((tmp = match(base, node->x.next->literal.next, s, n + node->x.next->literal.len)) != NO_MATCH) { + return tmp; + } + if (!n) { + break; + } + } + if (n == o) { + return match(base, node->x.next->literal.next, s, n + node->x.next->literal.len); + } + return NO_MATCH; + } + + for (n = St_len(s); n > o; --n) { + if ((tmp = match(base, node->x.next, s, n)) != NO_MATCH) { + return tmp; + } + } + return match(base, node->x.next, s, o); + } + + Mmatch1(match, ST_INDEX); +} + +static size_t iomatch(const t_regex *base, const re_node *node, IO *s, size_t o) { + + Mmatch0(iomatch, io_peek); + + case RE_BACKREF: + if ( + node->backref.n < base->captures && + base->cap_ptr[node->backref.n].start + 1u && + base->cap_ptr[node->backref.n].end + 1u && + base->cap_ptr[node->backref.n].end >= base->cap_ptr[node->backref.n].start && + ( + io_xcmp( + s, + base->cap_ptr[node->backref.n].start, + o, + base->cap_ptr[node->backref.n].end - base->cap_ptr[node->backref.n].start + ) == 0 + ) + ) { + return iomatch(base, node->backref.next, s, o + base->cap_ptr[node->backref.n].end - base->cap_ptr[node->backref.n].start); + } + return NO_MATCH; + + + case RE_LITERAL: + if ( + node->literal.len == 0 || + ( + io_cmppeek(s, o, node->literal.buf, node->literal.len) == 0 + ) + ) { + return iomatch(base, node->literal.next, s, o + node->literal.len); + } + return NO_MATCH; + + case RE_STUFF_FRUGAL: + if (!node->x.next) { + return o; + } + + for (; io_peek(s, o) != EOF; ++o) { + if ((tmp = iomatch(base, node->x.next, s, o)) != NO_MATCH) { + return tmp; + } + } + return iomatch(base, node->x.next, s, o); + + case RE_STUFF_GREEDY: { + size_t n; + + for (n = o; io_peek(s, n) != EOF; ++n) + ; + + if (!node->x.next) { + return n; + } + + for (; n > o; --n) { + if ((tmp = iomatch(base, node->x.next, s, n)) != NO_MATCH) { + return tmp; + } + } + return iomatch(base, node->x.next, s, o); + } + + Mmatch1(iomatch, io_peek); +} + +#define DEFRBUF ((void)0) +#define MRETURN(x) return (x) +#define INITRBUF(re) memset((re)->repbuf, '\0', (re)->repets * sizeof *(re)->repbuf) + +int re_iomatch(t_regex *re, IO *io, size_t *ms, size_t *me) { + size_t i; + DEFRBUF; + INITRBUF(re); + + assert(re != NULL); + assert(io != NULL); + assert(io_bufred(io)); + assert(ms != NULL); + assert(me != NULL); + + reinit(re); + + if (re->flags & FL_ANCHOR_START) { + if ((*me = iomatch(re, re->start, io, 0)) == NO_MATCH) { + MRETURN(0); + } + *ms = 0; + MRETURN(1); + } + + for (i = 0; io_peek(io, i) != EOF; ++i) { + if ((*me = iomatch(re, re->start, io, i)) != NO_MATCH) { + *ms = i; + MRETURN(1); + } + } + + if ((*me = iomatch(re, re->start, io, i)) != NO_MATCH) { + *ms = i; + MRETURN(1); + } + MRETURN(0); +} + +int re_match(t_regex *re, const String *s, size_t *ms, size_t *me) { + size_t i; + DEFRBUF; + INITRBUF(re); + + assert(re != NULL); + assert(s != NULL); + assert(ms != NULL); + assert(me != NULL); + + if (re->minlen > St_len(s)) { + MRETURN(0); + } + + reinit(re); + + if (re->flags & FL_ANCHOR_START) { + if ((*me = match(re, re->start, s, 0)) == NO_MATCH) { + MRETURN(0); + } + *ms = 0; + MRETURN(1); + } + + if (re->start->x.type == RE_LITERAL && re->start->literal.len) { + for ( + i = St_str_m(s, re->start->literal.buf, re->start->literal.len); + i + 1u; + i = St_stro_m(s, i + 1u, re->start->literal.buf, re->start->literal.len) + ) { + if ((*me = match(re, re->start->literal.next, s, i + re->start->literal.len)) != NO_MATCH) { + *ms = i; + MRETURN(1); + } + } + MRETURN(0); + } + + for (i = 0; i <= St_len(s) - re->minlen; ++i) { + if ((*me = match(re, re->start, s, i)) != NO_MATCH) { + *ms = i; + MRETURN(1); + } + } + + MRETURN(0); +} + +size_t re_cabra(const t_regex *re) { + return re->captures; +} + +int re_backref(const t_regex *re, size_t i, size_t *a, size_t *z) { + if (i >= re->captures) { + return -1; + } + if (!(re->cap_ptr[i].start + 1u && re->cap_ptr[i].end + 1u)) { + return 1; + } + *a = re->cap_ptr[i].start; + *z = re->cap_ptr[i].end; + return 0; +} + +ATTR_PURE +static const re_node *branchend(const re_node *a, const re_node *b) { + for (; a; a = a->x.next) { + const re_node *q = b; + for (; q; q = q->x.next) { + if (a == q) { + return q; + } + } + } + return NULL; +} + +static void decom_class(String *s, const unsigned char vec[HAVE_C99(static CLASS_SIZE)]) { + unsigned char i; + int flag = 0; + char big_enough[100]; + + for (i = 0; i < UCHAR_MAX; ++i) { + if (vec[i / CHAR_BIT] & 1u << i % CHAR_BIT) { + if (vec[(i + 1u) / CHAR_BIT] & 1u << (i + 1u) % CHAR_BIT) { + if (!flag) { + flag = 1; + goto mess; + } + flag = 1; + } else { + if (flag) { + if (i > 1u && vec[(i - 2u) / CHAR_BIT] & 1u << (i - 2u) % CHAR_BIT) { + St_cat_c(s, '-'); + } + flag = 0; + } +mess: + if (!isprint(i)) { + St_cat_c(s, '\\'); + switch (i) { + case '\a': St_cat_c(s, 'a'); break; + case '\b': St_cat_c(s, 'b'); break; + case '\f': St_cat_c(s, 'f'); break; + case '\n': St_cat_c(s, 'n'); break; + case '\r': St_cat_c(s, 'r'); break; + case '\t': St_cat_c(s, 't'); break; + case '\v': St_cat_c(s, 'v'); break; + default: + sprintf(big_enough, "%03o", (unsigned)i); + St_cat_s(s, big_enough); + break; + } + } else { + if (strchr("\\\"", (char)i)) { + St_cat_c(s, '\\'); + } + St_cat_c(s, i); + if (strchr("!'-", (char)i)) { + St_cat_c(s, ESCAPE); + } + } + } + } + } + if (vec[i / CHAR_BIT] & 1u << i % CHAR_BIT) { + if (flag) { + if (vec[(i - 2u) / CHAR_BIT] & 1u << (i - 2u) % CHAR_BIT) { + St_cat_c(s, '-'); + } + flag = 0; + } + if (!isprint(i)) { + St_cat_c(s, '\\'); + switch (i) { + case '\a': St_cat_c(s, 'a'); break; + case '\b': St_cat_c(s, 'b'); break; + case '\f': St_cat_c(s, 'f'); break; + case '\n': St_cat_c(s, 'n'); break; + case '\r': St_cat_c(s, 'r'); break; + case '\t': St_cat_c(s, 't'); break; + case '\v': St_cat_c(s, 'v'); break; + default: + sprintf(big_enough, "%03o", (unsigned)i); + St_cat_s(s, big_enough); + break; + } + } else { + if (strchr("\\\"", (char)i)) { + St_cat_c(s, '\\'); + } + St_cat_c(s, i); + if (strchr("!'-", (char)i)) { + St_cat_c(s, ESCAPE); + } + } + } +} + +static void dumpclass(FILE *fp, const unsigned char vec[HAVE_C99(static CLASS_SIZE)]) { + String tmp; + St_init(&tmp); + decom_class(&tmp, vec); + ST_WRITE(&tmp, fp); + St_clear(&tmp); +} + +ATTR_CONST +static int cdefclass(const unsigned char *ptr) { + if (ptr == dc_word) { return 'w'; } + if (ptr == dc_alpha) { return 'q'; } + if (ptr == dc_cntrl) { return 'c'; } + if (ptr == dc_digit) { return 'd'; } + if (ptr == dc_lower) { return 'l'; } + if (ptr == dc_print) { return 'p'; } + if (ptr == dc_space) { return 's'; } + if (ptr == dc_upper) { return 'u'; } + if (ptr == dc_xdigit) { return 'x'; } + NOTREACHED; +} + +static void decom_liter(String *s, const re_node *node) { + size_t i; + assert(node->x.type == RE_LITERAL || node->x.type == RE_PARTIAL); + for (i = 0; i < node->literal.len; ++i) { + if (!isprint((unsigned char)node->literal.buf[i])) { + St_cat_c(s, '\\'); + switch (node->literal.buf[i]) { + case '\a': St_cat_c(s, 'a'); break; + case '\b': St_cat_c(s, 'b'); break; + case '\f': St_cat_c(s, 'f'); break; + case '\n': St_cat_c(s, 'n'); break; + case '\r': St_cat_c(s, 'r'); break; + case '\t': St_cat_c(s, 't'); break; + case '\v': St_cat_c(s, 'v'); break; + default: { + char big_enough[100]; + sprintf(big_enough, "%03o", (unsigned)(unsigned char)node->literal.buf[i]); + St_cat_s(s, big_enough); + break; + } + } + } else { + if (node->x.type == RE_LITERAL && strchr("\"\\", node->literal.buf[i])) { + St_cat_c(s, '\\'); + } + St_cat_c(s, node->literal.buf[i]); + if (MEATCHARP(node->literal.buf[i])) { + St_cat_c(s, ESCAPE); + } + } + } +} + +static void dumpliter(FILE *fp, const re_node *node) { + String tmp; + St_init(&tmp); + decom_liter(&tmp, node); + ST_WRITE(&tmp, fp); + St_clear(&tmp); +} + +static void do_indent(FILE *fp, size_t n) { + for (; n; --n) { + fputs(" ", fp); + } +} + +static void dumpnode(FILE *fp, const re_node *node, const re_node *end, const size_t indent) { + if (node == end) { + return; + } + + assert(node != NULL); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + + switch (node->x.type) { + case RE_ALTER: { + const re_node *const be = branchend(node->alter.arg, node->alter.next); + fputs("branch {\n", fp); + dumpnode(fp, node->alter.arg, be, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} or {\n", fp); + dumpnode(fp, node->alter.next, be, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /branch\n", fp); + dumpnode(fp, be, end, indent); + return; + } + + case RE_ANYCH: + fputs("anychar\n", fp); + break; + + case RE_AT_BOL: + fputs("at beginning of line\n", fp); + break; + + case RE_AT_BOS: + fputs("at beginning of string\n", fp); + break; + + case RE_AT_EOL: + fputs("at end of line\n", fp); + break; + + case RE_AT_EOS: + fputs("at end of string\n", fp); + break; + + case RE_AT_MATCH: + fputs("at match {\n", fp); + dumpnode(fp, node->indep.arg, NULL, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /at match\n", fp); + break; + + case RE_AT_NOMATCH: + fputs("not at match {\n", fp); + dumpnode(fp, node->indep.arg, NULL, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /not at match\n", fp); + break; + + case RE_AT_NWBOUND: + fputs("not at word boundary\n", fp); + break; + + case RE_AT_WBOUND: + fputs("at word boundary\n", fp); + break; + + case RE_BACKCHECK: + fprintf(fp, "check capture (%lu)\n", (unsigned long)node->backref.n); + break; + + case RE_BACKREF: + fprintf(fp, "backref (%lu)\n", (unsigned long)node->backref.n); + break; + + case RE_BEGIN_CAPTURE: + fprintf(fp, "begin capture (%lu)\n", (unsigned long)node->backref.n); + break; + + case RE_CLASS: + fputs("character class '", fp); + dumpclass(fp, node->class.vec); + fputs("'\n", fp); + break; + + case RE_DEFCLASS: + fprintf(fp, "character class %c!\n", cdefclass(node->defclass.vec)); + break; + + case RE_END_CAPTURE: + fprintf(fp, "end capture (%lu)\n", (unsigned long)node->backref.n); + break; + + case RE_INDEP: + fputs("independent submatch {\n", fp); + dumpnode(fp, node->indep.arg, NULL, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /independent submatch\n", fp); + break; + + case RE_LITERAL: + fputs("literal \"", fp); + dumpliter(fp, node); + fputs("\"\n", fp); + break; + + case RE_N_CLASS: + fputs("negated character class '", fp); + dumpclass(fp, node->class.vec); + fputs("'\n", fp); + break; + + case RE_N_DEFCLASS: + fprintf(fp, "character class %c!\n", toupper(cdefclass(node->defclass.vec))); + break; + + case RE_PARTIAL: + fputs("abbreviation `", fp); + dumpliter(fp, node); + fputs("`\n", fp); + break; + + case RE_REP_FRUGAL: + fputs("repetition ", fp); + if (node->rep.min == node->rep.max) { + fprintf(fp, ":%lu:?", (unsigned long)node->rep.min); + } else if (node->rep.max != (size_t)-1) { + fprintf(fp, ":%lu,%lu:?", (unsigned long)node->rep.min, (unsigned long)node->rep.max); + } else { + switch (node->rep.min) { + case 0: fputs("*?", fp); break; + case 1: fputs("+?", fp); break; + default: fprintf(fp, ":%lu,:?", (unsigned long)node->rep.min); break; + } + } + fputs(" {\n", fp); + dumpnode(fp, node->rep.arg, node, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /repetition\n", fp); + break; + + case RE_REP_GREEDY: + fputs("repetition ", fp); + if (node->rep.min == node->rep.max) { + fprintf(fp, ":%lu:", (unsigned long)node->rep.min); + } else if (node->rep.max != (size_t)-1) { + fprintf(fp, ":%lu,%lu:", (unsigned long)node->rep.min, (unsigned long)node->rep.max); + } else { + switch (node->rep.min) { + case 0: fputs("*", fp); break; + case 1: fputs("+", fp); break; + default: fprintf(fp, ":%lu,:", (unsigned long)node->rep.min); break; + } + } + fputs(" {\n", fp); + dumpnode(fp, node->rep.arg, node, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /repetition\n", fp); + break; + + case RE_SELECT: { + const re_node *const be = branchend(node->select.arg, node->select.next); + fputs("if {\n", fp); + dumpnode(fp, node->select.cond, NULL, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} then {\n", fp); + dumpnode(fp, node->select.arg, be, indent + 1); + if (node->select.next != be) { + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} else {\n", fp); + dumpnode(fp, node->select.next, be, indent + 1); + } + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /if\n", fp); + dumpnode(fp, be, end, indent); + return; + } + + case RE_STUFF_FRUGAL: + fputs(".*?\n", fp); + break; + + case RE_STUFF_GREEDY: + fputs(".*\n", fp); + break; + + case RE_XREP_FRUGAL: + fputs("simple repetition ", fp); + if (node->rep.min == node->rep.max) { + fprintf(fp, ":%lu:?", (unsigned long)node->rep.min); + } else if (node->rep.max != (size_t)-1) { + fprintf(fp, ":%lu,%lu:?", (unsigned long)node->rep.min, (unsigned long)node->rep.max); + } else { + switch (node->rep.min) { + case 0: fputs("*?", fp); break; + case 1: fputs("+?", fp); break; + default: fprintf(fp, ":%lu,:?", (unsigned long)node->rep.min); break; + } + } + fputs(" {\n", fp); + dumpnode(fp, node->rep.arg, NULL, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /simple repetition\n", fp); + break; + + case RE_XREP_GREEDY: + fputs("simple repetition ", fp); + if (node->rep.min == node->rep.max) { + fprintf(fp, ":%lu:", (unsigned long)node->rep.min); + } else if (node->rep.max != (size_t)-1) { + fprintf(fp, ":%lu,%lu:", (unsigned long)node->rep.min, (unsigned long)node->rep.max); + } else { + switch (node->rep.min) { + case 0: fputs("*", fp); break; + case 1: fputs("+", fp); break; + default: fprintf(fp, ":%lu,:", (unsigned long)node->rep.min); break; + } + } + fputs(" {\n", fp); + dumpnode(fp, node->rep.arg, NULL, indent + 1); + fprintf(fp, "[%p] ", (const void *)node); + do_indent(fp, indent); + fputs("} /simple repetition\n", fp); + break; + } + dumpnode(fp, node->x.next, end, indent); +} + +void re_dump(const t_regex *re, FILE *fp) { + fprintf(fp, "RE: minlen=%lu, anchor=%s\n", (unsigned long)re->minlen, re->flags & FL_ANCHOR_START ? "start" : "none"); + dumpnode(fp, re->start, NULL, 0); +} + +static void cat_n(String *s, unsigned long n) { + char big_enough[100]; + sprintf(big_enough, "%lu", n); + St_cat_s(s, big_enough); +} + +static void decom_repeat(String *s, const re_node *node) { + assert( + node->x.type == RE_REP_FRUGAL || + node->x.type == RE_REP_GREEDY || + node->x.type == RE_XREP_FRUGAL || + node->x.type == RE_XREP_GREEDY + ); + + if (node->rep.min == 0 && node->rep.max == (size_t)-1) { + St_cat_c(s, '*'); + } else if (node->rep.min == 0 && node->rep.max == 1) { + St_cat_c(s, '?'); + } else if (node->rep.min == 1 && node->rep.max == (size_t)-1) { + St_cat_c(s, '+'); + } else if (node->rep.min == node->rep.max) { + St_cat_c(s, ':'); + cat_n(s, node->rep.min); + St_cat_c(s, ':'); + } else if (node->rep.max == (size_t)-1) { + St_cat_c(s, ':'); + cat_n(s, node->rep.min); + St_cat_m(s, ",:", 2); + } else { + St_cat_c(s, ':'); + cat_n(s, node->rep.min); + St_cat_c(s, ','); + cat_n(s, node->rep.max); + St_cat_c(s, ':'); + } + + if (node->rep.type == RE_REP_FRUGAL || node->rep.type == RE_XREP_FRUGAL) { + St_cat_c(s, '?'); + } +} + +static void decom_node(String *s, const re_node *node, const re_node *end) { + if (node == end) { + return; + } + + assert(node != NULL); + switch (node->x.type) { + case RE_ALTER: { + const re_node *const be = branchend(node->alter.arg, node->alter.next); + St_cat_c(s, '('); + decom_node(s, node->alter.arg, be); + St_cat_c(s, '|'); + decom_node(s, node->alter.next, be); + St_cat_c(s, ')'); + decom_node(s, be, end); + break; + } + + case RE_ANYCH: + St_cat_c(s, '.'); + decom_node(s, node->x.next, end); + break; + + case RE_AT_BOL: + St_cat_m(s, "A!", 2); + decom_node(s, node->x.next, end); + break; + + case RE_AT_BOS: + St_cat_c(s, '^'); + decom_node(s, node->x.next, end); + break; + + case RE_AT_EOL: + St_cat_m(s, "Z!", 2); + decom_node(s, node->x.next, end); + break; + + case RE_AT_EOS: + St_cat_c(s, '$'); + decom_node(s, node->x.next, end); + break; + + case RE_AT_MATCH: + St_cat_c(s, '['); + decom_node(s, node->indep.arg, NULL); + St_cat_m(s, "&]", 2); + decom_node(s, node->indep.next, end); + break; + + case RE_AT_NOMATCH: + St_cat_c(s, '['); + decom_node(s, node->indep.arg, NULL); + St_cat_m(s, "^]", 2); + decom_node(s, node->indep.next, end); + break; + + case RE_AT_NWBOUND: + St_cat_m(s, "B!", 2); + decom_node(s, node->x.next, end); + break; + + case RE_AT_WBOUND: + St_cat_m(s, "b!", 2); + decom_node(s, node->x.next, end); + break; + + case RE_BACKREF: + case RE_BACKCHECK: { + String tmp; + if (node->x.type == RE_BACKCHECK) { + St_cat_c(s, '['); + } + St_init(&tmp); +#if HAVE_VSNPRINTF_P + St_xprintf(&tmp, "%lu", (unsigned long)node->backref.n); +#else + St_num(&tmp, node->backref.n); +#endif + St_cat(s, &tmp); + St_clear(&tmp); + if (node->x.type == RE_BACKCHECK) { + St_cat_c(s, ']'); + } else { + St_cat_c(s, ESCAPE); + } + decom_node(s, node->backref.next, end); + break; + } + + case RE_BEGIN_CAPTURE: + St_cat_c(s, '{'); + decom_node(s, node->x.next, end); + break; + + case RE_CLASS: + St_cat_c(s, '\''); + decom_class(s, node->class.vec); + St_cat_c(s, '\''); + decom_node(s, node->class.next, end); + break; + + case RE_DEFCLASS: + St_cat_c(s, cdefclass(node->defclass.vec)); + St_cat_c(s, ESCAPE); + decom_node(s, node->defclass.next, end); + break; + + case RE_END_CAPTURE: + St_cat_c(s, '}'); + decom_node(s, node->x.next, end); + break; + + case RE_INDEP: + St_cat_c(s, '<'); + decom_node(s, node->indep.arg, NULL); + St_cat_c(s, '>'); + decom_node(s, node->indep.next, end); + break; + + case RE_LITERAL: + decom_liter(s, node); + decom_node(s, node->literal.next, end); + break; + + case RE_N_CLASS: + St_cat_m(s, "'^", 2); + decom_class(s, node->class.vec); + St_cat_c(s, '\''); + decom_node(s, node->class.next, end); + break; + + case RE_N_DEFCLASS: + St_cat_c(s, toupper(cdefclass(node->defclass.vec))); + St_cat_c(s, ESCAPE); + decom_node(s, node->defclass.next, end); + break; + + case RE_PARTIAL: + St_cat_c(s, '`'); + decom_liter(s, node); + St_cat_c(s, '`'); + break; + + case RE_REP_FRUGAL: + case RE_REP_GREEDY: + St_cat_c(s, '('); + decom_node(s, node->rep.arg, node); + St_cat_c(s, ')'); + decom_repeat(s, node); + decom_node(s, node->rep.next, end); + break; + + case RE_SELECT: { + const re_node *const be = branchend(node->select.arg, node->select.next); + St_cat_c(s, '['); + if (be != node->select.next) { + decom_node(s, node->select.next, be); + St_cat_c(s, '|'); + } + decom_node(s, node->select.arg, be); + St_cat_c(s, '('); + decom_node(s, node->select.cond, NULL); + St_cat_c(s, ')'); + St_cat_m(s, "?]", 2); + decom_node(s, be, end); + break; + } + + case RE_STUFF_FRUGAL: + St_cat_m(s, ".*?", 3); + decom_node(s, node->x.next, end); + break; + + case RE_STUFF_GREEDY: + St_cat_m(s, ".*", 2); + decom_node(s, node->x.next, end); + break; + + case RE_XREP_FRUGAL: + case RE_XREP_GREEDY: + St_cat_c(s, '('); + decom_node(s, node->rep.arg, NULL); + St_cat_c(s, ')'); + decom_repeat(s, node); + decom_node(s, node->rep.next, end); + break; + } +} + +void re_decompile(const t_regex *re, String *s) { + St_zero(s); + decom_node(s, re->start, NULL); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/re.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +re.o: re.c config.h IO.h Str.h hash.h main_io.h main_opt.h re.h xmalloc.h \ + zz.h re_block.c.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/re.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,31 @@ +#ifndef RE_H_ +#define RE_H_ + +#include "config.h" +#include "IO.h" +#include "Str.h" + +#include <stddef.h> +#include <stdio.h> + +typedef struct my_regex t_regex; + +void re_init(void); +void re_end(void); + +t_regex *re_compile(const String *); +void re_free(t_regex *); +t_regex *re_dup(t_regex *); + +ATTR_PURE +int re_match(t_regex *, const String *, size_t *, size_t *); +int re_iomatch(t_regex *, IO *, size_t *, size_t *); + +ATTR_PURE +size_t re_cabra(const t_regex *); +int re_backref(const t_regex *, size_t, size_t *, size_t *); + +void re_dump(const t_regex *, FILE *); +void re_decompile(const t_regex *, String *); + +#endif /* RE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/re_block.c.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,60 @@ +/* vi: set ft=c: */ +enum {BLOCK_MAGIC = 32}; + +struct block_node { + struct block_node *next; + size_t used; + re_node nodes[BLOCK_MAGIC]; +}; + +struct txt_node { + struct txt_node *next; + unsigned char *buf; +}; + +typedef struct { + struct block_node *root; + struct txt_node *txt_root; +} t_block; + +static void bl_init(t_block *b) { + b->root = xmalloc(1, sizeof *b->root); + b->root->next = NULL; + b->root->used = 0; + b->txt_root = NULL; +} + +static void bl_free(t_block *b) { + while (b->root) { + struct block_node *tmp = b->root->next; + xfree(b->root); + b->root = tmp; + } + + while (b->txt_root) { + struct txt_node *tmp = b->txt_root->next; + xfree(b->txt_root->buf); + xfree(b->txt_root); + b->txt_root = tmp; + } +} + +static re_node *bl_node(t_block *b) { + if (b->root->used >= sizeof b->root->nodes / sizeof b->root->nodes[0]) { + struct block_node *tmp = xmalloc(1, sizeof *tmp); + tmp->used = 0; + tmp->next = b->root; + b->root = tmp; + } + + return b->root->nodes + b->root->used++; +} + +static unsigned char *bl_string(t_block *b, size_t len) { + struct txt_node *tmp = xmalloc(1, sizeof *tmp); + tmp->buf = xmalloc(len, sizeof *tmp->buf); + tmp->next = b->txt_root; + b->txt_root = tmp; + + return b->txt_root->buf; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/run.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,458 @@ +#include "config.h" +#include "IO.h" +#include "Str.h" +#include "atechit.h" +#include "expr.h" +#include "hang.h" +#include "main.h" +#include "main_io.h" +#include "main_label.h" +#include "main_opt.h" +#include "run.h" +#include "stack.h" +#include "strhash.h" +#include "text.h" +#include "val.h" +#include "venus.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <errno.h> +#include <math.h> +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <setjmp.h> + +struct Interp Interp; + +static void my_x_end(void) { + v_end(&Interp.arg); + v_end(&Interp.result); + + while (Interp.a.argc) { + --Interp.a.argc; + v_end(&Interp.a.argv[Interp.a.argc]); + } + xfree(Interp.a.argv); + + while (Interp.match.length) { + --Interp.match.length; + v_end(&Interp.match.matches[Interp.match.length]); + } + xfree(Interp.match.matches); + + xfree(Interp.m_start.index); + xfree(Interp.m_end.index); +} + +static void sp_nop(save_pair *sp) { + (void)sp; +} + +static void sp_writeback(save_pair *sp) { + v_set(sp->target, &sp->content); + v_end(&sp->content); +} + +ATTR_NORETURN +static void sp_error(const save_pair *x, const save_pair *y) { + (void)x; + (void)y; + NOTREACHED; +} + +stack_define(save_pair, extern, sp_nop, sp_writeback, sp_error) + +stack(save_pair) Saved; + +void stack_store(struct val *target, const struct val *value) { + save_pair *tos; + + stack_func(save_pair, pushnull)(&Saved); + tos = stack_func(save_pair, at)(&Saved, 0); + + tos->target = target; + v_iniset(&tos->content, target); + v_set(target, value); +} + +static void stack_store_del(struct val *target, struct val *value) { + stack_store(target, value); + v_delete(value); +} + +size_t depth_get(void) { + return stack_func(save_pair, size)(&Saved); +} + +void depth_restore(size_t n) { + assert(depth_get() >= n); + stack_func(save_pair, clear)(&Saved, depth_get() - n); +} + +struct val *execute(const struct op *op, struct val *arg) { + struct val *v; + const size_t curdepth = depth_get(); + + stack_store_del(&Interp.arg, arg); + + while (op) { + if (Opt.debug & DBG_OPS) { + fprintf(io_fp(Err), "op %d\n", op->type); + } + switch (op->type) { + case OP_NOP: + break; + + case OP_ASSIGN: + if (!op->arh.expr) { + eval_into(op->arg, &Interp.result); + } else { + switch (op->arh.expr->type) { + case varE: + eval_into(op->arg, op->arh.expr->v.val); + break; + + case varhashE: { + struct val *tmp; + eval_push(op->arg); + eval_push(op->arh.expr->right); + tmp = eval_pop(); + v = eval_pop(); + V_STR(tmp); + sh_put(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko), v); + v_delete(tmp); + break; + } + + default: + NOTREACHED; + break; + } + } + break; + + case OP_CALL: + v = eval_expr(op->arg); + v = execute(op->arh.op, v); + v_set(&Interp.result, v); + v_delete(v); + break; + + case OP_CALL_BACK: { + struct op *tmp; + + v = eval_expr(op->arh.expr); + TOLABEL(v); + if (!(tmp = ve_findprev(&Venus, ko_str(v->ko), op->line))) { + v_delete(v); + hang(); + } + v_delete(v); + v = eval_expr(op->arg); + v = execute(tmp, v); + v_set(&Interp.result, v); + v_delete(v); + break; + } + + case OP_CALL_DYN: { + struct op *tmp; + + v = eval_expr(op->arg); + TOLABEL(v); + if (!(tmp = ve_findnext(&Venus, ko_str(v->ko), op->line))) { + v_delete(v); + hang(); + } + v_set_undef(v); + v = execute(tmp, v); + v_set(&Interp.result, v); + v_delete(v); + break; + } + + case OP_CLOSE: + v = eval_expr(op->arg); + if (V_EXT_P(v)) { + v_set_n(&Interp.result, io_close(v->magic.ext)); + } else { + v_set_n(&Interp.result, -1); + #ifdef EBADF + errno = EBADF; + #endif + } + v_delete(v); + break; + + case OP_EXIT: { + int tmp; + + v = eval_expr(op->arg); + V_NUM(v); + tmp = v->num >= 0.0 ? v->num + .5 : EXIT_FAILURE; + v_delete(v); + exit(tmp); + } + + case OP_FLUSH: + v = eval_expr(op->arg); + if (!V_EXT_P(v)) { + v_delete(v); + v_set_n(&Interp.result, EOF); + #ifdef EBADF + errno = EBADF; + #endif + break; + } + v_set_n(&Interp.result, io_flush(v->magic.ext)); + v_delete(v); + break; + + case OP_GOBACK: + v = eval_expr(op->arg); + TOLABEL(v); + if ((op = ve_findprev(&Venus, ko_str(v->ko), op->line))) { + v_delete(v); + continue; + } + v_delete(v); + hang(); + break; + + case OP_GOTO: + v = eval_expr(op->arg); + TOLABEL(v); + if ((op = ve_findnext(&Venus, ko_str(v->ko), op->line))) { + v_delete(v); + continue; + } + v_delete(v); + hang(); + break; + + case OP_ELSE: + case OP_HANG: + case OP_FI: + hang(); + break; + + case OP_IF: + v = eval_expr(op->arg); + if (v_true(v)) { + v_delete(v); + op = op->arh.op; + continue; + } + v_delete(v); + break; + + case OP_MODIFY: { + struct val *tmp = eval_expr(op->arg); + expr_pp(op->arh.expr->op, op->arh.expr->v.val, tmp); + v_delete(tmp); + break; + } + + case OP_PRINT: { + IO *fh; + + eval_push(op->arg); + if (!op->arh.expr) { + fh = io_incr(Out); + } else { + struct val *const tmp = eval_expr(op->arh.expr); + + if (V_EXT_P(tmp)) { + fh = io_incr(tmp->magic.ext); + } else { + v_delete(tmp); + v_delete(eval_pop()); + v_set_n(&Interp.result, -1); + #ifdef EBADF + errno = EBADF; + #endif + break; + } + v_delete(tmp); + } + v = eval_pop(); + V_STR(v); + v_set_n(&Interp.result, io_write_m(fh, ko_ptr(v->ko), ko_length(v->ko)) + 1u - 1.); + io_decr(fh); + v_delete(v); + break; + } + + case OP_PUTC: { + IO *fh; + + eval_push(op->arg); + if (!op->arh.expr) { + fh = io_incr(Out); + } else { + struct val *const tmp = eval_expr(op->arh.expr); + + if (V_EXT_P(tmp)) { + fh = io_incr(tmp->magic.ext); + } else { + v_delete(tmp); + v_delete(eval_pop()); + v_set_n(&Interp.result, -1); + #ifdef EBADF + errno = EBADF; + #endif + break; + } + v_delete(tmp); + } + v = eval_pop(); + V_NUM(v); + + v_set_n(&Interp.result, io_putc(fh, RINT(v->num))); + io_decr(fh); + v_delete(v); + break; + } + + case OP_RESET: + v = eval_expr(op->arg); + if (!V_EXT_P(v)) { + v_delete(v); + v_set_n(&Interp.result, EOF); + #ifdef EBADF + errno = EBADF; + #endif + break; + } + io_clearerr(v->magic.ext); + v_delete(v); + break; + + case OP_RETURN: + if (op->arg->type == unopE && op->arg->op == F_CALL) { + eval_into(op->arg->right, &Interp.arg); + op = op->arg->left.op; + continue; + } + v = eval_expr(op->arg); + depth_restore(curdepth); + return v; + + case OP_SET_VAL: + switch (op->arh.expr->type) { + case varE: + v_set(op->arh.expr->v.val, op->arg->v.val); + break; + + case varhashE: { + struct val *const tmp = eval_expr(op->arh.expr->right); + struct val *const val = v_undef(); + V_STR(tmp); + v_set(val, op->arg->v.val); + sh_put(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko), val); + v_delete(tmp); + break; + } + + default: + NOTREACHED; + break; + } + break; + + case OP_SYSTEM: + v = eval_expr(op->arg); + V_STR(v); + v_set_n(&Interp.result, system(ko_szp(v->ko))); + v_delete(v); + break; + + case OP_TEMP: + eval_push(op->arg); + if (!op->arh.expr) { + v_delete(eval_pop()); + } else switch (op->arh.expr->type) { + case varE: + stack_store_del(op->arh.expr->v.val, eval_pop()); + break; + + case varhashE: { + struct val *addr; + struct val *const tmp = eval_expr(op->arh.expr->right); + v = eval_pop(); + V_STR(tmp); + if (!(addr = sh_get(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko)))) { + sh_put(op->arh.expr->v.hash, ko_ptr(tmp->ko), ko_length(tmp->ko), addr = v_undef()); + } + v_delete(tmp); + stack_store_del(addr, v); + break; + } + + default: + NOTREACHED; + } + break; + + case OP_THROW: + v = eval_expr(op->arg); + if (!depth_get()) { + V_STR(v); + if (ko_at(v->ko, ko_length(v->ko) - 1u) == '\n') { + io_write_m(Err, ko_ptr(v->ko), ko_length(v->ko)); + } else { + fprintf(io_fp(Err), "%s: uncaught exception: ", Prog); + io_write_m(Err, ko_ptr(v->ko), ko_length(v->ko)); + putc('\n', io_fp(Err)); + } + v_delete(v); + exit(EXIT_FAILURE); + } + v_set(&Interp.result, v); + v_delete(v); + longjmp(stack_func(t_context, at)(&Context, 0)->buf, 1); + break; + } + op = op->next; + } + + exit(0); +} + +static void cleanup(void) { + stack_func(save_pair, end)(&Saved); +} + +void run(const struct text *t, size_t argc, char **argv) { + int status; + struct val *result; + + v_init(&Interp.arg); + v_init(&Interp.result); + + Interp.a.argv = xmalloc(argc, sizeof *Interp.a.argv); + for (Interp.a.argc = 0; Interp.a.argc < argc; ++Interp.a.argc) { + struct val *const tmp = &Interp.a.argv[Interp.a.argc]; + v_init(tmp); + v_set_m(tmp, argv[Interp.a.argc], strlen(argv[Interp.a.argc])); + } + + Interp.match.matches = xmalloc(Interp.match.size = 2, sizeof *Interp.match.matches); + Interp.match.length = 0; + + Interp.m_start.index = xmalloc(Interp.m_start.size = 0, sizeof *Interp.m_start.index); + Interp.m_end.index = xmalloc(Interp.m_end.size = 0, sizeof *Interp.m_end.index); + + stack_func(save_pair, init)(&Saved); + atechit(cleanup); + atechit(my_x_end); + + result = execute(t->start[0], v_undef()); + V_NUM(result); + status = result->num >= 0.0 ? result->num + .5 : EXIT_FAILURE; + v_delete(result); + exit(status); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/run.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +run.o: run.c config.h IO.h Str.h atechit.h expr.h op.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h hang.h main.h \ + main_io.h main_label.h mars.h venus.h hash.h main_opt.h run.h text.h \ + zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/run.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,51 @@ +#ifndef RUN_H_ +#define RUN_H_ + +#include "config.h" +#include "op.h" +#include "text.h" +#include "val.h" +#include "stack.h" + +#include <stddef.h> + +struct val *execute(const struct op *, struct val *); +ATTR_NORETURN +void run(const struct text *, size_t, char **); + +struct Interp { + struct val arg; + struct val result; + + struct { + struct val *argv; + size_t argc; + } a; + struct { + struct val *matches; + size_t length, size; + } match; + struct { + size_t *index; + size_t size; + } m_start; + struct { + size_t *index; + size_t size; + } m_end; +}; +extern struct Interp Interp; + +typedef struct { + struct val *target; + struct val content; +} save_pair; + +stack_declare(save_pair, extern) +extern stack(save_pair) Saved; + +void stack_store(struct val *, const struct val *); +size_t depth_get(void); +void depth_restore(size_t); + +#endif /* RUN_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/stack.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,103 @@ +#ifndef STACK_H_ +#define STACK_H_ + +#include "config.h" +#include "xmalloc.h" + +#include <stddef.h> + +#define stack(T) struct T##STACK +#define stack_func(T, f) T##STACK##f + +#define stack_declare(T, X) \ + \ +stack(T) { \ + T *arr; \ + size_t size, length; \ +}; \ + \ +X void stack_func(T, init)(stack(T) *); \ +X void stack_func(T, end)(stack(T) *); \ +X void stack_func(T, clear)(stack(T) *, size_t); \ + \ +X void stack_func(T, push)(stack(T) *, const T *); \ +X void stack_func(T, pushnull)(stack(T) *); \ +X int stack_func(T, pop)(stack(T) *, T *); \ +/* X int stack_func(T, peek)(const stack(T) *, T *); */ \ +ATTR_PURE \ +X T *stack_func(T, at)(const stack(T) *, size_t); \ +ATTR_PURE \ +X size_t stack_func(T, size)(const stack(T) *); \ +/* end of declaration */ + +#define stack_define(T, X, prepare, clean, copy) \ +X void stack_func(T, init)(stack(T) *s) { \ + s->arr = xmalloc(s->size = 7, sizeof *s->arr); \ + s->length = 0; \ +} \ + \ +X void stack_func(T, end)(stack(T) *s) { \ + while (s->length) { \ + --s->length; \ + (clean)(&s->arr[s->length]); \ + } \ + xfree(s->arr); \ + s->arr = 0; \ +} \ + \ +X void stack_func(T, clear)(stack(T) *s, size_t n) { \ + while (n && s->length) { \ + --n; \ + --s->length; \ + (clean)(&s->arr[s->length]); \ + } \ +} \ + \ +X void stack_func(T, push)(stack(T) *s, const T *x) { \ + if (s->length >= s->size) { \ + s->arr = xrealloc(s->arr, s->size *= 2); \ + } \ + (prepare)(&s->arr[s->length]); \ + (copy)(&s->arr[s->length], x); \ + ++s->length; \ +} \ + \ +X void stack_func(T, pushnull)(stack(T) *s) { \ + if (s->length >= s->size) { \ + s->arr = xrealloc(s->arr, s->size *= 2); \ + } \ + (prepare)(&s->arr[s->length]); \ + ++s->length; \ +} \ + \ +X int stack_func(T, pop)(stack(T) *s, T *x) { \ + if (s->length) { \ + --s->length; \ + (copy)(x, &s->arr[s->length]); \ + (clean)(&s->arr[s->length]); \ + return 0; \ + } \ + return 1; \ +} \ + \ +/* X int stack_func(T, peek)(const stack(T) *s, T *x) { \ + if (s->length) { \ + (copy)(x, &s->arr[s->length - 1]); \ + return 0; \ + } \ + return 1; \ +} */ \ + \ +X size_t stack_func(T, size)(const stack(T) *s) { \ + return s->length; \ +} \ + \ +X T *stack_func(T, at)(const stack(T) *s, size_t n) { \ + if (n < s->length) { \ + return &s->arr[s->length - n - 1u]; \ + } \ + return NULL; \ +} \ +/* end of definition */ + +#endif /* STACK_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/strhash.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,65 @@ +#include "hash.h" +#include "strhash.h" +#include "strutil.h" +#include "xmalloc.h" + +#include <string.h> + +struct strx { + char *ptr; + size_t length; +}; + +struct strx_const { + const char *ptr; + size_t length; +}; + +struct strhash { + Hash hash; +}; + +static size_t hash(const void *p, size_t h) { + const struct strx *const s = p; + return u_hash(s->ptr, s->length, h); +} + +static int compar(const void *ap, const void *bp) { + const struct strx *const a = ap, *const b = bp; + return u_cmp(a->ptr, a->length, b->ptr, b->length); +} + +static void delk(void *p) { + struct strx *const s = p; + xfree(s->ptr); + xfree(s); +} + +t_strhash *sh_new(void (*delv)(void *)) { + t_strhash *sh = xmalloc(1, sizeof *sh); + h_init(&sh->hash, hash, compar, delk, delv); + return sh; +} + +void sh_delete(t_strhash *sh) { + h_end(&sh->hash); + xfree(sh); +} + +void sh_put(t_strhash *sh, const char *key, size_t keylen, void *val) { + struct strx *dup = xmalloc(1, sizeof *dup); + dup->ptr = xmalloc(dup->length = keylen, sizeof *dup->ptr); + memcpy(dup->ptr, key, keylen); + h_put(&sh->hash, dup, val, 1); +} + +void *sh_get(t_strhash *sh, const char *key, size_t keylen) { + void *p; + struct strx_const tmp; + tmp.ptr = key; + tmp.length = keylen; + if (h_get(&sh->hash, &tmp, &p) == H_OK) { + return p; + } + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/strhash.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +strhash.o: strhash.c hash.h strhash.h config.h strutil.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/strhash.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,16 @@ +#ifndef STRHASH_H_ +#define STRHASH_H_ + +#include "config.h" + +#include <stddef.h> + +typedef struct strhash t_strhash; + +t_strhash *sh_new(void (*)(void *)); +void sh_delete(t_strhash *); + +void sh_put(t_strhash *, const char *, size_t, void *); +void *sh_get(t_strhash *, const char *, size_t); + +#endif /* STRHASH_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/strutil.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,34 @@ +#include "strutil.h" + +#include <string.h> + +/* FYI: This is the "One-at-a-Time" algorithm by Bob Jenkins + * from requirements by Colin Plumb. + * (http://burtleburtle.net/bob/hash/doobs.html) */ +size_t u_hash(const char *s, size_t l, size_t h) { + size_t i; + + for (i = 0; i < l; ++i) { + h += (unsigned char)s[i]; + h += h << 10; + h ^= h >> 6; + } + h += h << 3; + h ^= h >> 11; + h += h << 15; + + return h; +} + +int u_cmp(const char *as, size_t al, const char *bs, size_t bl) { + int tmp; + if (as == bs && al == bl) + return 0; + if ((tmp = memcmp(as, bs, al < bl ? al : bl))) + return tmp; + if (al < bl) + return -1; + if (al > bl) + return 1; + return 0; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/strutil.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +strutil.o: strutil.c strutil.h config.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/strutil.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,13 @@ +#ifndef STRUTIL_H_ +#define STRUTIL_H_ + +#include "config.h" + +#include <stddef.h> + +ATTR_PURE +size_t u_hash(const char *, size_t, size_t); +ATTR_PURE +int u_cmp(const char *, size_t, const char *, size_t); + +#endif /* STRUTIL_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/sub.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,134 @@ +#include "expr.h" +#include "main_opt.h" +#include "sub.h" +#include "transmogrify.h" +#include "xmalloc.h" + +#include <stddef.h> + +struct sub { + struct expr *expr; + size_t refs; + size_t id; +}; + +static struct expr *dup(const struct expr *e) { + struct expr *p; + + if (!e) { + return NULL; + } + + p = xmalloc(1, sizeof *p); + *p = *e; + + switch (e->type) { + case literE: + p->v.val = v_undef(); + v_set(p->v.val, e->v.val); + break; + + case varE: + break; + + case varhashE: + p->right = dup(e->right); + break; + + case symbolE: + switch (e->op) { + case S_ARGV: + p->right = dup(e->right); + break; + } + break; + + case unopE: + p->right = dup(e->right); + if (e->op == F_MATCH) { + p->left.rx = re_dup(e->left.rx); + } + break; + + case binopE: + case listE: + p->right = dup(e->right); + p->left.expr = dup(e->left.expr); + break; + } + + return p; +} + +static void solid(struct expr *e) { + if (!e) { + return; + } + + switch (e->type) { + case literE: + break; + + case varE: + e->v.val = eval_expr(e); + e->type = literE; + break; + + case varhashE: + break; + + case symbolE: + switch (e->op) { + case S_ARGV: + solid(e->right); + break; + } + break; + + case unopE: + solid(e->right); + break; + + case binopE: + case listE: + solid(e->left.expr); + solid(e->right); + break; + } +} + +struct sub *sub_new(const struct expr *e) { + static size_t idcount; + struct sub *p; + p = xmalloc(1, sizeof *p); + p->expr = dup(e); + solid(p->expr); + if (!Opt.unoptimize) { + trans_fold(&p->expr); + } + p->refs = 0; + p->id = idcount++; + return p; +} + +struct sub *sub_incr(struct sub *p) { + ++p->refs; + return p; +} + +void sub_decr(struct sub *p) { + if (!p->refs) { + free_expr(p->expr); + xfree(p); + return; + } + --p->refs; +} + +struct expr *sub_expr(const struct sub *p) { + return p->expr; +} + +size_t sub_id(const struct sub *p) { + return p->id; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/sub.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +sub.o: sub.c expr.h config.h Str.h op.h IO.h re.h stack.h xmalloc.h \ + strhash.h val.h kork.h list.h sub.h variable.h main_opt.h \ + transmogrify.h text.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/sub.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,18 @@ +#ifndef SUB_H_ +#define SUB_H_ + +#include "config.h" + +#include <stddef.h> + +struct expr; +struct sub; + +struct sub *sub_new(const struct expr *); +struct sub *sub_incr(struct sub *); +void sub_decr(struct sub *); +ATTR_PURE +struct expr *sub_expr(const struct sub *); +size_t sub_id(const struct sub *); + +#endif /* SUB_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/syntax/ploki.vim Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,74 @@ +" Vim syntax file +" Language: ploki +" Maintainer: Lukas Mai +" Last Change: 2010-02-28 +" Version: 0.15 + +if version < 600 + sy clear +elseif exists('b:current_syntax') + finish +endif + +syn match plokiStuff /.\+/ contains=plokiList,plokiNumber,plokiSpcErr,plokiSpecial,plokiFunc,plokiString contained + +syn match plokiList /#<\|#>/ +syn match plokiNumber /\.\d\+\%([Ee][-+]\=\d\+\)\=/ +syn match plokiNumber /\d\+\%(\.\d*\)\=\%([Ee][-+]\=\d\+\)\=/ +syn match plokiSpcErr /\\/ +syn match plokiSpecial + \ /\\\%([!?@_]\|\d\+\|ARG\|AUSG\|EING\|E\|FEHL\|PI\)\=/ +syn match plokiFunc /\\\%(ARG:\|ENV\|[LQRU]\)/ +syn match plokiFunc + \ /@\%([-+]\|ABS\|ACOS\|APERS\|ASIN\|ATAN2\=\|CHR\|COS\|DEF-P\|EDD-P\|ENV\|ERR-P\|EVAL\|GET\|INT\|IO-P\|LAPERS\|LEGS\|LENGTH\|L[GN]\|NEG\|NOT\|NUM\|OMFG\|ORD\|RE\%(MOVE\|NAEM\|VERSE\)\|SAG\|SAPERS\|SIN\|SQRT\|STR\|SUCH\|TAN\|TYPE OF\)/ +syn match plokiEscErr /\\/ contained +syn match plokiEscape /\\\%([abfnrtv"\\V]\|c.\|x\x\x\=\|\o\{1,3}\)/ contained +syn match plokiString '"\%(\%(??/\n\)\@![^"\\]\)*\%(\\c\=.\%(\%(??/\n\)\@![^"\\]\)*\)*"\=' + \ contains=plokiEscape,plokiEscErr nextgroup=plokiCont +syn match plokiGarbage '\%(\%(??/\n\)\@!.\)\+' contained nextgroup=plokiCont +syn match plokiCmd + \ /#\|A[BN]RUF\|CLAUDS\|END\|FLUSH\|GO\%(FOR\|TO\)\|IACS\|IF\|KTHX\|LEE\=T\|RESET\|SET\|WUNT/ + \ contained +syn match plokiCmd /#!\|ELSE\|END IF\|FI/ contained nextgroup=plokiGarbage +syn region plokiComment matchgroup=plokiCmd start=/REM/ end=/$/ + \ contained contains=plokiComment +syn match plokiWord /\S\+/ contained nextgroup=plokiGarbage +syn match plokiCmd /NEXT\s*/ contained nextgroup=plokiWord +syn match plokiLabel /^\s*\%(FOR\s*\S\+\|\d*\)\s*/ + \ nextgroup=plokiCmd,plokiComment,plokiSpcErr,plokiSpecial,plokiFunc,plokiString +" ^... around a bug(?) + +syn match plokiCont '??/\n' nextgroup=plokiStuff + +syn match plokiInsert /^\s*INSERT\%(\%( DA\)\=\)\@>\s*\S\+\%(\s\+\S\+\)*\s*HERE\s*$/ contains=plokiInsFile +syn match plokiInsFile /\%(^\s*INSERT\%(\%( DA\)\=\)\@>\s*\)\@<=\S\+\%(\s\+\S\+\)*\%(\s*HERE\s*$\)\@=/ contained + +if version >= 508 || !exists('did_ploki_syn_inits') + if version < 508 + let did_ploki_syn_inits = 1 + command -nargs=+ HiLink hi link <args> + else + command -nargs=+ HiLink hi def link <args> + endif + + HiLink plokiinsFile String + HiLink plokiInsert Preproc + HiLink plokiCont Preproc + HiLink plokiLabel Label + HiLink plokiGarbage Comment + HiLink plokiComment Comment + HiLink plokiCmd Type + HiLink plokiWord Label + HiLink plokiString String + HiLink plokiEscape SpecialChar + HiLink plokiEscErr Error + HiLink plokiFunc Function + HiLink plokiSpecial Special + HiLink plokiSpcErr Error + HiLink plokiNumber Number + HiLink plokiList Preproc + + delc HiLink +endif + +let b:current_syntax = 'ploki'
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/t/00-compile.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,6 @@ +#!ploki +"1..4 +"ok 1 +"ok 2\n" +WUNT "ok 3 +WUNT \AUSG "ok 4\n"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/t/10-regress.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,79 @@ +#!ploki +"1..8 +(#<"ok 1"#> . 0 _ " + +IF @NOT ("X" ~ "[{.}^]|{.}" + "not " +ELSE + IF \0 ; "X" | (\1 ; "") + "not " + FI +FI +"ok 2 + +IF @NOT ("Y" ~ "<{.}>Z|{.}" + "not " +ELSE + IF \0 ; "Y" | (\1 ; "") + "not " + FI +FI +"ok 3 + +IF @NOT ("Z" ~ "[{.}&]X|{.}" + "not " +ELSE + IF \0 ; "Z" | (\1 ; "") + "not " + FI +FI +"ok 4 + +(#<"not " "ok "#> [ 1 _ #<5#> _ " + +LET f @OMFG @throw \@ +LET e "E" +LET x @EVAL #<"A" (f . e)#> +IF x ; "" | (\_ ; e) + "not " +FI +"ok 6 + +LET fh @APERS #<"/ this file does not exist!" "RF"#> +IF fh + CLAUDS fh + "not " +FI +"ok 7 + +LET n "tmp.txt" +LET fh @APERS #<n "W+"#> +IF @NOT fh + WUNT \FEHL "open: " _ n _ ": " _ \! _ " + END 1 +END IF +LET txt "zomg +WUNT fh txt +IF @SUCH #<fh 0#> + WUNT \FEHL "seek: " _ n _ ": " _ \! _ " + END 1 +FI +LET s fh . @NEG 1 +IF @ERR-P fh + WUNT \FEHL "read: " _ n _ ": " _ \! _ " + END 1 +FI +CLAUDS fh +IF \_ + WUNT \FEHL "close: " _ n _ ": " _ \! _ " + END 1 +END IF +LET () @REMOVE n +IF s ; txt + "not " +FI +"ok 8 + +END + +FOR throw IACS \@
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/tags Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1109 @@ +!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/ +!_TAG_FILE_SORTED 1 /0=unsorted, 1=sorted, 2=foldcase/ +!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/ +!_TAG_PROGRAM_NAME Exuberant Ctags // +!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/ +!_TAG_PROGRAM_VERSION 5.7 // +ARITH pp.c 555;" d file: +ATECHIT_H_ atechit.h 2;" d +ATTR config.h 74;" d +ATTR config.h 76;" d +ATTR config.h 87;" d +ATTR_CONST config.h 95;" d +ATTR_MALLOC config.h 80;" d +ATTR_MALLOC config.h 83;" d +ATTR_MALLOC config.h 88;" d +ATTR_NORETURN config.h 93;" d +ATTR_PURE config.h 81;" d +ATTR_PURE config.h 84;" d +ATTR_PURE config.h 89;" d +ATTR_SPRINTF config.h 94;" d +ATTR_UNUSED config.h 92;" d +Afunc atechit.c /^static void (*Afunc[MAGIC])(void);$/;" v file: +Aused atechit.c /^static size_t Aused;$/;" v file: +BADF IO.c 246;" d file: +BADF IO.c 248;" d file: +BLOCK_MAGIC re_block.c.h /^enum {BLOCK_MAGIC = 32};$/;" e enum:__anon33 +B_AMPERSAND expr.h /^ B_AMPERSAND,$/;" e enum:t_binop +B_ANGLE expr.h /^ B_ANGLE,$/;" e enum:t_binop +B_BACKSPARK expr.h /^ B_BACKSPARK,$/;" e enum:t_binop +B_BRACELET expr.h /^ B_BRACELET,$/;" e enum:t_binop +B_DOUBLE_OH_SEVEN expr.h /^ B_DOUBLE_OH_SEVEN,$/;" e enum:t_binop +B_EMBRACE expr.h /^ B_EMBRACE,$/;" e enum:t_binop +B_FLATWORM expr.h /^ B_FLATWORM,$/;" e enum:t_binop +B_HALF_MESH expr.h /^ B_HALF_MESH,$/;" e enum:t_binop +B_HYBRID expr.h /^ B_HYBRID,$/;" e enum:t_binop +B_INTERSECTION expr.h /^ B_INTERSECTION,$/;" e enum:t_binop +B_RIGHT_ANGLE expr.h /^ B_RIGHT_ANGLE,$/;" e enum:t_binop +B_SHARK_FIN expr.h /^ B_SHARK_FIN,$/;" e enum:t_binop +B_SLAT expr.h /^ B_SLAT,$/;" e enum:t_binop +B_SPARK expr.h /^ B_SPARK,$/;" e enum:t_binop +B_SPARK_SPOT expr.h /^ B_SPARK_SPOT,$/;" e enum:t_binop +B_SPIKE expr.h /^ B_SPIKE,$/;" e enum:t_binop +B_SPLAT expr.h /^ B_SPLAT,$/;" e enum:t_binop +B_SPOT expr.h /^ B_SPOT,$/;" e enum:t_binop +B_SQIGGLE expr.h /^ B_SQIGGLE,$/;" e enum:t_binop +B_TAIL expr.h /^ B_TAIL,$/;" e enum:t_binop +B_TWO_SPOT expr.h /^ B_TWO_SPOT,$/;" e enum:t_binop +B_U_TURN expr.h /^ B_U_TURN,$/;" e enum:t_binop +B_U_TURN_BACK expr.h /^ B_U_TURN_BACK,$/;" e enum:t_binop +B_WORM expr.h /^ B_WORM,$/;" e enum:t_binop +B_XMATCH expr.h /^ B_XMATCH$/;" e enum:t_binop +CALL re.c 231;" d file: +CASE expr.c 580;" d file: +CASE expr.c 731;" d file: +CASE_DO_STUFF expr.c 572;" d file: +CASE_DO_STUFF expr.c 730;" d file: +CCLASS_CHECK re.c 712;" d file: +CLASS_SIZE re.c /^enum {CLASS_SIZE = UCHAR_MAX \/ CHAR_BIT + 1u};$/;" e enum:__anon9 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon11 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon12 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon13 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon14 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon15 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon16 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon17 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon18 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon19 file: +CMN_HDR re.c /^ CMN_HDR;$/;" m struct:my_node::__anon20 file: +CMN_HDR re.c 99;" d file: +CMP_LS pp.c 587;" d file: +CMP_N pp.c 593;" d file: +CNCLASS_CHECK re.c 713;" d file: +COMPILE_H_ compile.h 2;" d +CONFIG_H_ config.h 2;" d +CPY Str.c 399;" d file: +CUSTOM_REP_CASE re.c 912;" d file: +CXCLASS_CHECK re.c 703;" d file: +DBG_HASH main_opt.h /^ DBG_HASH = 2 * DBG_OPS,$/;" e enum:Options::__anon31 +DBG_OPS main_opt.h /^ DBG_OPS = 1,$/;" e enum:Options::__anon31 +DBG_REGEX main_opt.h /^ DBG_REGEX = 2 * DBG_HASH$/;" e enum:Options::__anon31 +DEBUG config.h 5;" d +DEBUG config.h 8;" d +DEBUG_P config.h 6;" d +DEBUG_P config.h 9;" d +DECL_PP1 pp.h 50;" d +DECL_PP1 pp.h 6;" d +DECL_PP2 pp.h 52;" d +DECL_PP2 pp.h 79;" d +DEFRBUF re.c 1918;" d file: +DELKV hash.c 52;" d file: +DEPARSE_H_ deparse.h 2;" d +DIR_END config.h 14;" d +DIR_END config.h 16;" d +DIR_END config.h 19;" d +DI_NONE IO.c /^ DI_NONE,$/;" e enum:IO::__anon1 file: +DI_RD IO.c /^ DI_RD,$/;" e enum:IO::__anon1 file: +DI_WR IO.c /^ DI_WR$/;" e enum:IO::__anon1 file: +DO_SLEEP config.h 25;" d +DO_SLEEP config.h 29;" d +DO_SLEEP config.h 32;" d +ENDBRANCHP re.c 200;" d file: +ESCAPE re.c /^enum {ESCAPE = '!'};$/;" e enum:__anon21 file: +EXPR_H_ expr.h 2;" d +Err main.c /^IO *In, *Out, *Err;$/;" v +FL_ANCHOR_START re.c /^ FL_ANCHOR_START = 1$/;" e enum:re_flags file: +FL_NONE re.c /^ FL_NONE = 0,$/;" e enum:re_flags file: +F_ABS expr.h /^ F_ABS,$/;" e enum:t_func +F_ACOS expr.h /^ F_ACOS,$/;" e enum:t_func +F_ASIN expr.h /^ F_ASIN,$/;" e enum:t_func +F_ATAN expr.h /^ F_ATAN,$/;" e enum:t_func +F_ATAN2 expr.h /^ F_ATAN2,$/;" e enum:t_func +F_CALL expr.h /^ F_CALL = -1,$/;" e enum:t_func +F_CATCH expr.h /^ F_CATCH,$/;" e enum:t_func +F_CHR expr.h /^ F_CHR,$/;" e enum:t_func +F_COS expr.h /^ F_COS,$/;" e enum:t_func +F_DEFINED expr.h /^ F_DEFINED,$/;" e enum:t_func +F_EOF expr.h /^ F_EOF,$/;" e enum:t_func +F_ERROR expr.h /^ F_ERROR,$/;" e enum:t_func +F_EXP expr.h /^ F_EXP,$/;" e enum:t_func +F_FREEZE expr.h /^ F_FREEZE,$/;" e enum:t_func +F_GETC expr.h /^ F_GETC,$/;" e enum:t_func +F_GETENV expr.h /^ F_GETENV,$/;" e enum:t_func +F_GETS expr.h /^ F_GETS,$/;" e enum:t_func +F_HANG expr.h /^ F_HANG,$/;" e enum:t_func +F_INT expr.h /^ F_INT,$/;" e enum:t_func +F_IO expr.h /^ F_IO,$/;" e enum:t_func +F_LENGTH expr.h /^ F_LENGTH,$/;" e enum:t_func +F_LOG expr.h /^ F_LOG,$/;" e enum:t_func +F_LOG10 expr.h /^ F_LOG10,$/;" e enum:t_func +F_LOWER expr.h /^ F_LOWER,$/;" e enum:t_func +F_MATCH expr.h /^ F_MATCH,$/;" e enum:t_func +F_MOEND expr.h /^ F_MOEND,$/;" e enum:t_func +F_MOSTART expr.h /^ F_MOSTART,$/;" e enum:t_func +F_NEG expr.h /^ F_NEG,$/;" e enum:t_func +F_NOT expr.h /^ F_NOT,$/;" e enum:t_func +F_NUL expr.h /^ F_NUL,$/;" e enum:t_func +F_NUM expr.h /^ F_NUM,$/;" e enum:t_func +F_OPEN expr.h /^ F_OPEN,$/;" e enum:t_func +F_OPENR expr.h /^ F_OPENR,$/;" e enum:t_func +F_OPENW expr.h /^ F_OPENW,$/;" e enum:t_func +F_ORD expr.h /^ F_ORD,$/;" e enum:t_func +F_QUOTE expr.h /^ F_QUOTE,$/;" e enum:t_func +F_REMOVE expr.h /^ F_REMOVE,$/;" e enum:t_func +F_RENAME expr.h /^ F_RENAME,$/;" e enum:t_func +F_REVERSE expr.h /^ F_REVERSE,$/;" e enum:t_func +F_RE_ESC expr.h /^ F_RE_ESC,$/;" e enum:t_func +F_SEEK expr.h /^ F_SEEK,$/;" e enum:t_func +F_SIN expr.h /^ F_SIN,$/;" e enum:t_func +F_SQRT expr.h /^ F_SQRT,$/;" e enum:t_func +F_STR expr.h /^ F_STR,$/;" e enum:t_func +F_TAN expr.h /^ F_TAN,$/;" e enum:t_func +F_TELL expr.h /^ F_TELL,$/;" e enum:t_func +F_TYPEOF expr.h /^ F_TYPEOF,$/;" e enum:t_func +F_UPPER expr.h /^ F_UPPER$/;" e enum:t_func +HANG_H_ hang.h 2;" d +HASH_H_ hash.h 2;" d +HAVE_C99 config.h 58;" d +HAVE_C99 config.h 61;" d +HAVE_C99_P config.h 57;" d +HAVE_C99_P config.h 60;" d +HAVE_DEV_URANDOM_P config.h 36;" d +HAVE_DEV_URANDOM_P config.h 38;" d +HAVE_GCC config.h 66;" d +HAVE_GCC config.h 69;" d +HAVE_GCC_P config.h 65;" d +HAVE_GCC_P config.h 68;" d +HAVE_SLEEP_P config.h 23;" d +HAVE_SLEEP_P config.h 27;" d +HAVE_SLEEP_P config.h 31;" d +HAVE_VSNPRINTF config.h 103;" d +HAVE_VSNPRINTF config.h 106;" d +HAVE_VSNPRINTF config.h 110;" d +HAVE_VSNPRINTF config.h 98;" d +HAVE_VSNPRINTF_P config.h 104;" d +HAVE_VSNPRINTF_P config.h 107;" d +HAVE_VSNPRINTF_P config.h 111;" d +HAVE_VSNPRINTF_P config.h 99;" d +H_EXIST hash.h /^ H_EXIST,$/;" e enum:__anon30 +H_NOENT hash.h /^ H_NOENT$/;" e enum:__anon30 +H_OK hash.h /^ H_OK,$/;" e enum:__anon30 +Hash hash.h /^} Hash;$/;" t typeref:struct:__anon29 +IF_DB xmalloc.c 12;" d file: +IF_DB xmalloc.c 14;" d file: +INC_H_ inc.h 2;" d +INC_PREFIX config.h 43;" d +INC_PREFIX config.h 45;" d +INC_PREFIX_LIST config.h 49;" d +INITRBUF re.c 1920;" d file: +IO IO.c /^struct IO {$/;" s file: +IO IO.h /^typedef struct IO IO;$/;" t typeref:struct:IO +IOS_CUR IO.h /^ IOS_CUR = SEEK_CUR,$/;" e enum:io_whence +IOS_END IO.h /^ IOS_END = SEEK_END$/;" e enum:io_whence +IOS_START IO.h /^ IOS_START = SEEK_SET,$/;" e enum:io_whence +IO_APPEND IO.h /^ IO_APPEND = 2 * IO_WRITE,$/;" e enum:io_flags +IO_AUTOFLUSH IO.h /^ IO_AUTOFLUSH = 2 * IO_BUFFERED$/;" e enum:io_flags +IO_BINARY IO.h /^ IO_BINARY = 1,$/;" e enum:io_flags +IO_BUFFERED IO.h /^ IO_BUFFERED = 2 * IO_TRUNCATE,$/;" e enum:io_flags +IO_H_ IO.h 2;" d +IO_READ IO.h /^ IO_READ = 2 * IO_BINARY,$/;" e enum:io_flags +IO_TRUNCATE IO.h /^ IO_TRUNCATE = 2 * IO_APPEND,$/;" e enum:io_flags +IO_WRITE IO.h /^ IO_WRITE = 2 * IO_READ,$/;" e enum:io_flags +In main.c /^IO *In, *Out, *Err;$/;" v +Interp run.c /^struct Interp Interp;$/;" v typeref:struct:Interp +Interp run.h /^struct Interp {$/;" s +KORK_H_ kork.h 2;" d +LIST_H_ list.h 2;" d +LOGIC pp.c 561;" d file: +MAGIC Str.c /^enum {MAGIC = 4};$/;" e enum:__anon2 file: +MAGIC atechit.c /^enum {MAGIC = 23};$/;" e enum:__anon3 file: +MAGIC deparse.c /^enum {MAGIC = 23};$/;" e enum:__anon5 file: +MAGIC hash.c /^enum {MAGIC = 112};$/;" e enum:__anon6 file: +MAGIC list.c /^enum {MAGIC = 7};$/;" e enum:__anon7 file: +MAGIC mars.c /^enum {MAGIC = 128};$/;" e enum:__anon8 file: +MAGIC re.c /^enum {MAGIC = 23};$/;" e enum:__anon10 file: +MAGIC text.c /^enum {MAGIC = 42};$/;" e enum:__anon22 file: +MAGIC variable.c /^enum {MAGIC = 23};$/;" e enum:__anon23 file: +MAGIC venus.c /^enum {MAGIC = 23};$/;" e enum:__anon24 file: +MAIN_H_ main.h 2;" d +MAIN_IO_H_ main_io.h 2;" d +MAIN_LABEL_H_ main_label.h 2;" d +MAIN_OPT_H_ main_opt.h 2;" d +MAIN_VAR_H_ main_var.h 2;" d +MAKE_LABEL deparse.c 18;" d file: +MAKE_LABEL deparse.c 25;" d file: +MARS_H_ mars.h 2;" d +MATCH_H_ match.h 2;" d +MEATCHARP re.c 199;" d file: +MIN Str.c 735;" d file: +MRETURN re.c 1919;" d file: +MY_E expr.c 37;" d file: +MY_E expr.c 39;" d file: +MY_PI expr.c 31;" d file: +MY_PI expr.c 33;" d file: +Mars main.c /^struct mars Mars;$/;" v typeref:struct:mars +Mmatch0 re.c 1443;" d file: +Mmatch1 re.c 1542;" d file: +NAME main.c 34;" d file: +NCMP Str.c 191;" d file: +NDEBUG config.h 10;" d +NOTREACHED zz.h 9;" d +NO_MATCH re.c 1441;" d file: +NUMB pp.c 548;" d file: +OFFSET_OFF Str.c 17;" d file: +OPERATORS expr.h 164;" d +OPERATOR_P expr.h 165;" d +OPT_H_ opt.h 2;" d +OP_1ARG_P op.h 52;" d +OP_2ARG_P op.h 60;" d +OP_ASSIGN op.h /^ OP_ASSIGN,$/;" e enum:t_op +OP_CALL op.h /^ OP_CALL,$/;" e enum:t_op +OP_CALL_BACK op.h /^ OP_CALL_BACK,$/;" e enum:t_op +OP_CALL_DYN op.h /^ OP_CALL_DYN,$/;" e enum:t_op +OP_CLOSE op.h /^ OP_CLOSE,$/;" e enum:t_op +OP_ELSE op.h /^ OP_ELSE,$/;" e enum:t_op +OP_EXIT op.h /^ OP_EXIT,$/;" e enum:t_op +OP_FI op.h /^ OP_FI,$/;" e enum:t_op +OP_FLUSH op.h /^ OP_FLUSH,$/;" e enum:t_op +OP_GOBACK op.h /^ OP_GOBACK,$/;" e enum:t_op +OP_GOTO op.h /^ OP_GOTO,$/;" e enum:t_op +OP_HANG op.h /^ OP_HANG,$/;" e enum:t_op +OP_H_ op.h 2;" d +OP_IF op.h /^ OP_IF,$/;" e enum:t_op +OP_MODIFY op.h /^ OP_MODIFY,$/;" e enum:t_op +OP_NOP op.h /^ OP_NOP,$/;" e enum:t_op +OP_PRINT op.h /^ OP_PRINT,$/;" e enum:t_op +OP_PUTC op.h /^ OP_PUTC,$/;" e enum:t_op +OP_RESET op.h /^ OP_RESET,$/;" e enum:t_op +OP_RETURN op.h /^ OP_RETURN,$/;" e enum:t_op +OP_SET_VAL op.h /^ OP_SET_VAL,$/;" e enum:t_op +OP_SYSTEM op.h /^ OP_SYSTEM,$/;" e enum:t_op +OP_TEMP op.h /^ OP_TEMP,$/;" e enum:t_op +OP_THROW op.h /^ OP_THROW$/;" e enum:t_op +Opt main.c /^struct Options Opt;$/;" v typeref:struct:Options +Options main_opt.h /^struct Options {$/;" s +Out main.c /^IO *In, *Out, *Err;$/;" v +PARSE_H_ parse.h 2;" d +PMODE IO.c 260;" d file: +PP_H_ pp.h 2;" d +PRAZ re.c /^PRAZ(alternation) {$/;" f +PRAZ re.c /^PRAZ(atom) {$/;" f +PRAZ re.c /^PRAZ(branch) {$/;" f +PRAZ re.c /^PRAZ(literal) {$/;" f +PRAZ re.c /^PRAZ(quantifire) {$/;" f +PRAZ re.c 229;" d file: +PUSH_SEEN deparse.c 517;" d file: +Prog main.c /^const char *Prog = NAME;$/;" v +RANDOM_H_ random.h 2;" d +RETURN_REP re.c 894;" d file: +RE_ALTER re.c /^ RE_ALTER,$/;" e enum:t_re_node file: +RE_ANYCH re.c /^ RE_ANYCH,$/;" e enum:t_re_node file: +RE_AT_BOL re.c /^ RE_AT_BOL,$/;" e enum:t_re_node file: +RE_AT_BOS re.c /^ RE_AT_BOS,$/;" e enum:t_re_node file: +RE_AT_EOL re.c /^ RE_AT_EOL,$/;" e enum:t_re_node file: +RE_AT_EOS re.c /^ RE_AT_EOS,$/;" e enum:t_re_node file: +RE_AT_MATCH re.c /^ RE_AT_MATCH,$/;" e enum:t_re_node file: +RE_AT_NOMATCH re.c /^ RE_AT_NOMATCH,$/;" e enum:t_re_node file: +RE_AT_NWBOUND re.c /^ RE_AT_NWBOUND,$/;" e enum:t_re_node file: +RE_AT_WBOUND re.c /^ RE_AT_WBOUND,$/;" e enum:t_re_node file: +RE_BACKCHECK re.c /^ RE_BACKCHECK,$/;" e enum:t_re_node file: +RE_BACKREF re.c /^ RE_BACKREF,$/;" e enum:t_re_node file: +RE_BEGIN_CAPTURE re.c /^ RE_BEGIN_CAPTURE,$/;" e enum:t_re_node file: +RE_CLASS re.c /^ RE_CLASS,$/;" e enum:t_re_node file: +RE_DEFCLASS re.c /^ RE_DEFCLASS,$/;" e enum:t_re_node file: +RE_END_CAPTURE re.c /^ RE_END_CAPTURE,$/;" e enum:t_re_node file: +RE_H_ re.h 2;" d +RE_INDEP re.c /^ RE_INDEP,$/;" e enum:t_re_node file: +RE_LITERAL re.c /^ RE_LITERAL,$/;" e enum:t_re_node file: +RE_N_CLASS re.c /^ RE_N_CLASS,$/;" e enum:t_re_node file: +RE_N_DEFCLASS re.c /^ RE_N_DEFCLASS,$/;" e enum:t_re_node file: +RE_PARTIAL re.c /^ RE_PARTIAL,$/;" e enum:t_re_node file: +RE_REP_FRUGAL re.c /^ RE_REP_FRUGAL,$/;" e enum:t_re_node file: +RE_REP_GREEDY re.c /^ RE_REP_GREEDY,$/;" e enum:t_re_node file: +RE_SELECT re.c /^ RE_SELECT,$/;" e enum:t_re_node file: +RE_STUFF_FRUGAL re.c /^ RE_STUFF_FRUGAL,$/;" e enum:t_re_node file: +RE_STUFF_GREEDY re.c /^ RE_STUFF_GREEDY,$/;" e enum:t_re_node file: +RE_XREP_FRUGAL re.c /^ RE_XREP_FRUGAL,$/;" e enum:t_re_node file: +RE_XREP_GREEDY re.c /^ RE_XREP_GREEDY$/;" e enum:t_re_node file: +RINT val.h 78;" d +RMODE IO.c 261;" d file: +RSTR Str.c 317;" d file: +RUN_H_ run.h 2;" d +Root IO.c /^static IO *Root;$/;" v file: +Root xmalloc.c /^} *Root;$/;" v typeref:struct:node file: +SLEEP_HEADER config.h 24;" d +SLEEP_HEADER config.h 28;" d +SNAP transmogrify.c 288;" d file: +SNORK re.c 230;" d file: +STACK_H_ stack.h 2;" d +STD_REP_CASE re.c 906;" d file: +STR Str.c 284;" d file: +STRHASH_H_ strhash.h 2;" d +STRUTIL_H_ strutil.h 2;" d +STR_H_ Str.h 2;" d +ST_FIRSTCHAR Str.h 140;" d +ST_INDEX Str.h 141;" d +ST_LASTCHAR Str.h 139;" d +ST_WRITE Str.h 142;" d +SUB_H_ sub.h 2;" d +S_ARG expr.h /^ S_ARG,$/;" e enum:t_symbol +S_ARGC expr.h /^ S_ARGC,$/;" e enum:t_symbol +S_ARGV expr.h /^ S_ARGV,$/;" e enum:t_symbol +S_ERR expr.h /^ S_ERR,$/;" e enum:t_symbol +S_EULER expr.h /^ S_EULER,$/;" e enum:t_symbol +S_LUDOLF expr.h /^ S_LUDOLF,$/;" e enum:t_symbol +S_MATCH expr.h /^ S_MATCH,$/;" e enum:t_symbol +S_NUL expr.h /^ S_NUL,$/;" e enum:t_symbol +S_RAND expr.h /^ S_RAND,$/;" e enum:t_symbol +S_RESULT expr.h /^ S_RESULT,$/;" e enum:t_symbol +S_STDERR expr.h /^ S_STDERR$/;" e enum:t_symbol +S_STDIN expr.h /^ S_STDIN,$/;" e enum:t_symbol +S_STDOUT expr.h /^ S_STDOUT,$/;" e enum:t_symbol +St_cat Str.c /^St_cat(String *s, const String *t) {$/;" f +St_cat_c Str.c /^St_cat_c(String *s, int c) {$/;" f +St_cat_m Str.c /^St_cat_m(String *s, const void *m, size_t n) {$/;" f +St_cat_s Str.c /^St_cat_s(String *s, const char *tz) {$/;" f +St_chr Str.c /^St_chr(const String *s, int c) {$/;" f +St_clear Str.c /^St_clear(String *s) {$/;" f +St_cmp Str.c /^St_cmp(const String *s, const String *t) {$/;" f +St_cmp_m Str.c /^St_cmp_m(const String *s, const void *m, size_t n) {$/;" f +St_cpy Str.c /^St_cpy(String *s, const String *t) {$/;" f +St_cpy_c Str.c /^St_cpy_c(String *s, int c) {$/;" f +St_cpy_m Str.c /^St_cpy_m(String *s, const void *m, size_t n) {$/;" f +St_cpy_s Str.c /^St_cpy_s(String *s, const char *tz) {$/;" f +St_del Str.c /^St_del(String *s, size_t p, size_t n) {$/;" f +St_fake Str.c /^St_fake(String *s, char *p, size_t n) {$/;" f +St_grep Str.c /^St_grep(String *s, int (*good)(int)) {$/;" f +St_grow Str.c /^St_grow(String *s, size_t n) {$/;" f file: +St_hash Str.c /^St_hash(const String *s, size_t h) {$/;" f +St_init Str.c /^St_init(String *s) {$/;" f +St_len Str.h 137;" d +St_lower Str.c /^St_lower(String *s) {$/;" f +St_ncmp_m Str.c /^St_ncmp_m(const String *s, const void *m, size_t n) {$/;" f +St_num Str.c /^St_num(String *s, double d) {$/;" f +St_ptr Str.h 136;" d +St_read Str.c /^St_read(String *s, FILE *fp, size_t n) {$/;" f +St_reverse Str.c /^St_reverse(String *s) {$/;" f +St_rstr_m Str.c /^St_rstr_m(const String *s, const void *m, size_t n) {$/;" f +St_rstr_s Str.c /^St_rstr_s(const String *s, const char *tz) {$/;" f +St_rstro_m Str.c /^St_rstro_m(const String *s, size_t off, const void *m, size_t n) {$/;" f +St_shift Str.c /^St_shift(String *s) {$/;" f +St_shiftws Str.c /^St_shiftws(String *s) {$/;" f +St_str Str.c /^St_str(const String *s, const String *t) {$/;" f +St_str_m Str.c /^St_str_m(const String *s, const void *m, size_t n) {$/;" f +St_stro_m Str.c /^St_stro_m(const String *s, size_t off, const void *m, size_t n) {$/;" f +St_substr Str.c /^St_substr(String *l, String *s, size_t p, size_t n, const String *r) {$/;" f +St_tac_c Str.c /^St_tac_c(String *s, int c) {$/;" f +St_tac_m Str.c /^St_tac_m(String *s, const void *m, size_t n) {$/;" f +St_tac_s Str.c /^St_tac_s(String *s, const char *tz) {$/;" f +St_trunc Str.c /^St_trunc(String *s, size_t n) {$/;" f +St_upper Str.c /^St_upper(String *s) {$/;" f +St_xprintf Str.c /^St_xprintf(String *s, const char *fmt, ...) {$/;" f +St_zero Str.h 138;" d +String Str.h /^} String;$/;" t typeref:struct:__anon25 +TAC Str.c 470;" d file: +TAILC re.c 232;" d file: +TEXT_H_ text.h 2;" d +TOLABEL expr.h 167;" d +TOS expr.c 785;" d file: +TRANSMOGRIFY_H_ transmogrify.h 2;" d +VAL_H_ val.h 2;" d +VARIABLE_H_ variable.h 2;" d +VENUS_H_ venus.h 2;" d +VERSION_H_ version.h 2;" d +VR_NO_COOKIE variable.h 10;" d +V_EXT_K val.h /^ V_EXT_K = V_NUM_K << 1,$/;" e enum:val_cont +V_EXT_P val.h 57;" d +V_LIST_K val.h /^ V_LIST_K = V_SUB_K << 1$/;" e enum:val_cont +V_LIST_P val.h 59;" d +V_NUM val.h 62;" d +V_NUM_K val.h /^ V_NUM_K = V_STR_K << 1,$/;" e enum:val_cont +V_NUM_P val.h 56;" d +V_STR val.h 61;" d +V_STR_K val.h /^ V_STR_K = 1,$/;" e enum:val_cont +V_STR_P val.h 55;" d +V_SUB_K val.h /^ V_SUB_K = V_EXT_K << 1,$/;" e enum:val_cont +V_SUB_P val.h 58;" d +V_UNDEF val.h /^ V_UNDEF = 0,$/;" e enum:val_cont +V_xxx_OFF val.h 64;" d +Var_hash main.c /^t_vr_container *Var_plain, *Var_hash;$/;" v +Var_plain main.c /^t_vr_container *Var_plain, *Var_hash;$/;" v +Venus main.c /^struct venus Venus;$/;" v typeref:struct:venus +Version version.c /^const char *Version =$/;" v +WARN main.c 35;" d file: +WMODE IO.c 259;" d file: +XFACTOR xmalloc.c 61;" d file: +XMALLOC_H_ xmalloc.h 2;" d +XMODE IO.c 251;" d file: +XRESIZN hash.c 107;" d file: +XSTEP hash.c 108;" d file: +ZZ_H_ zz.h 2;" d +a run.h /^ } a;$/;" m struct:Interp typeref:struct:Interp::__anon35 +alloc re.c /^ t_block alloc;$/;" m struct:my_regex file: +alter re.c /^ } alter;$/;" m union:my_node typeref:struct:my_node::__anon12 file: +alternation re.c /^PRAZ(alternation);$/;" v +anchorbegp re.c /^static int anchorbegp(const re_node *node) {$/;" f file: +arg op.h /^ struct expr *arg;$/;" m struct:op typeref:struct:op::expr +arg re.c /^ union my_node *arg;$/;" m struct:my_node::__anon12 typeref:union:my_node::__anon12::my_node file: +arg re.c /^ union my_node *arg;$/;" m struct:my_node::__anon17 typeref:union:my_node::__anon17::my_node file: +arg re.c /^ union my_node *arg;$/;" m struct:my_node::__anon19 typeref:union:my_node::__anon19::my_node file: +arg re.c /^ union my_node *arg;$/;" m struct:my_node::__anon20 typeref:union:my_node::__anon20::my_node file: +arg run.h /^ struct val arg;$/;" m struct:Interp typeref:struct:Interp::val +argc run.h /^ size_t argc;$/;" m struct:Interp::__anon35 +argv run.h /^ struct val *argv;$/;" m struct:Interp::__anon35 typeref:struct:Interp::__anon35::val +arh op.h /^ } arh;$/;" m struct:op typeref:union:op::__anon32 +array venus.c /^ struct op **array;$/;" m struct:sorted typeref:struct:sorted::op file: +atechit atechit.c /^void atechit(void (*f)(void)) {$/;" f +backref re.c /^ } backref;$/;" m union:my_node typeref:struct:my_node::__anon13 file: +bah atechit.c /^static void bah(void) {$/;" f file: +base re.c /^ t_regex *base;$/;" m struct:parse_context file: +binopE expr.h /^ binopE,$/;" e enum:t_expr +bl_free re_block.c.h /^static void bl_free(t_block *b) {$/;" f +bl_init re_block.c.h /^static void bl_init(t_block *b) {$/;" f +bl_node re_block.c.h /^static re_node *bl_node(t_block *b) {$/;" f +bl_string re_block.c.h /^static unsigned char *bl_string(t_block *b, size_t len) {$/;" f +block re.c /^ t_block *block;$/;" m struct:parse_context file: +block_node re_block.c.h /^struct block_node {$/;" s +bonus expr.h /^ size_t bonus;$/;" m union:expr::__anon27 +branch re.c /^PRAZ(branch);$/;" v +branchend re.c /^static const re_node *branchend(const re_node *a, const re_node *b) {$/;" f file: +brk hash.h /^ size_t brk;$/;" m struct:__anon29 +buf IO.c /^ String *buf;$/;" m struct:IO file: +buf Str.h /^ char *buf;$/;" m struct:__anon25 +buf expr.h /^ jmp_buf buf;$/;" m struct:__anon28 +buf re.c /^ unsigned char *buf;$/;" m struct:my_node::__anon18 file: +buf re_block.c.h /^ unsigned char *buf;$/;" m struct:txt_node +bufk IO.c /^static void bufk(IO *f, size_t n) {$/;" f file: +cached re.c /^static String cached[MAGIC];$/;" v file: +cachfill re.c /^static size_t cachfill, cachlast;$/;" v file: +cachlast re.c /^static size_t cachfill, cachlast;$/;" v file: +cap_ptr re.c /^ struct cap_state *cap_ptr;$/;" m struct:my_regex typeref:struct:my_regex::cap_state file: +cap_state re.c /^struct cap_state {$/;" s file: +capture re.c /^ } capture;$/;" m union:my_node typeref:struct:my_node::__anon14 file: +captures re.c /^ size_t captures;$/;" m struct:my_regex file: +cat Str.c /^static void cat(String *s, const void *m, size_t n) {$/;" f file: +cat_n re.c /^static void cat_n(String *s, unsigned long n) {$/;" f file: +cdefclass re.c /^static int cdefclass(const unsigned char *ptr) {$/;" f file: +class re.c /^ } class;$/;" m union:my_node typeref:struct:my_node::__anon15 file: +cleanup run.c /^static void cleanup(void) {$/;" f file: +cmp hash.h /^ int (*cmp)(const void *, const void *);$/;" m struct:__anon29 +compar re.c /^static int compar(const void *a, const void *b) {$/;" f file: +compar strhash.c /^static int compar(const void *ap, const void *bp) {$/;" f file: +compar venus.c /^static int compar(const void *a, const void *b) {$/;" f file: +compile compile.c /^void compile(struct text *code) {$/;" f +con_error expr.c /^static void con_error(const t_context *x, const t_context *y) {$/;" f file: +con_nop expr.c /^static void con_nop(t_context *c) {$/;" f file: +cond re.c /^ union my_node *cond;$/;" m struct:my_node::__anon20 typeref:union:my_node::__anon20::my_node file: +const_binop transmogrify.c 51;" d file: +const_unop transmogrify.c 37;" d file: +content run.h /^ struct val content;$/;" m struct:__anon39 typeref:struct:__anon39::val +data mars.h /^ struct op *data;$/;" m struct:mars typeref:struct:mars::op +data variable.h /^ void **data;$/;" m struct:__anon41 +dc_alpha re.c /^static unsigned char dc_alpha[CLASS_SIZE];$/;" v file: +dc_cntrl re.c /^static unsigned char dc_cntrl[CLASS_SIZE];$/;" v file: +dc_digit re.c /^static unsigned char dc_digit[CLASS_SIZE];$/;" v file: +dc_lower re.c /^static unsigned char dc_lower[CLASS_SIZE];$/;" v file: +dc_print re.c /^static unsigned char dc_print[CLASS_SIZE];$/;" v file: +dc_space re.c /^static unsigned char dc_space[CLASS_SIZE];$/;" v file: +dc_upper re.c /^static unsigned char dc_upper[CLASS_SIZE];$/;" v file: +dc_word re.c /^static unsigned char dc_word[CLASS_SIZE];$/;" v file: +dc_xdigit re.c /^static unsigned char dc_xdigit[CLASS_SIZE];$/;" v file: +debug main_opt.h /^ } debug;$/;" m struct:Options typeref:enum:Options::__anon31 +decom_class re.c /^static void decom_class(String *s, const unsigned char vec[HAVE_C99(static CLASS_SIZE)]) {$/;" f file: +decom_liter re.c /^static void decom_liter(String *s, const re_node *node) {$/;" f file: +decom_node re.c /^static void decom_node(String *s, const re_node *node, const re_node *end) {$/;" f file: +decom_repeat re.c /^static void decom_repeat(String *s, const re_node *node) {$/;" f file: +decouple list.c /^static void decouple(struct list *l, size_t slack) {$/;" f file: +decr kork.c /^static void decr(dolphin *dp) {$/;" f file: +decr list.c /^static void decr(whale *wp) {$/;" f file: +defclass re.c /^ } defclass;$/;" m union:my_node typeref:struct:my_node::__anon16 file: +del variable.h /^ void (*del)(void *);$/;" m struct:__anon41 +delcookie variable.c /^static void delcookie(void *c) {$/;" f file: +delk hash.h /^ void (*delk)(void *);$/;" m struct:__anon29 +delk strhash.c /^static void delk(void *p) {$/;" f file: +delk venus.c /^static void delk(void *k) {$/;" f file: +delv hash.h /^ void (*delv)(void *);$/;" m struct:__anon29 +delv re.c /^static void delv(void *v) {$/;" f file: +delv venus.c /^static void delv(void *v) {$/;" f file: +deparse deparse.c /^void deparse(const struct text *t) {$/;" f +deparse main_opt.h /^ int deparse;$/;" m struct:Options +depth expr.h /^ size_t depth;$/;" m struct:__anon28 +depth_get run.c /^size_t depth_get(void) {$/;" f +depth_restore run.c /^void depth_restore(size_t n) {$/;" f +dirct IO.c /^ } dirct;$/;" m struct:IO typeref:enum:IO::__anon1 file: +display deparse.c /^static int display(enum t_binop b) {$/;" f file: +do_indent re.c /^static void do_indent(FILE *fp, size_t n) {$/;" f file: +do_match match.c /^void do_match(struct val *v, t_regex *re) {$/;" f +do_stuff deparse.c /^static void do_stuff(struct op *op) {$/;" f file: +dolphin kork.c /^typedef struct ko_dolphin dolphin;$/;" t typeref:struct:ko_dolphin file: +dostuff re.c /^static void dostuff(t_regex *re) {$/;" f file: +dump_expr deparse.c /^static void dump_expr(const struct expr *e, int inlist) {$/;" f file: +dump_ko deparse.c /^static void dump_ko(const struct kork *k) {$/;" f file: +dump_op deparse.c /^static void dump_op(struct op *op) {$/;" f file: +dump_str deparse.c /^static void dump_str(const String *s) {$/;" f file: +dumpclass re.c /^static void dumpclass(FILE *fp, const unsigned char vec[HAVE_C99(static CLASS_SIZE)]) {$/;" f file: +dumpliter re.c /^static void dumpliter(FILE *fp, const re_node *node) {$/;" f file: +dumpnode re.c /^static void dumpnode(FILE *fp, const re_node *node, const re_node *end, const size_t indent) {$/;" f file: +dup sub.c /^static struct expr *dup(const struct expr *e) {$/;" f file: +end re.c /^ size_t start, end, pending;$/;" m struct:cap_state file: +end_if compile.c /^static struct op *end_if(struct text *code, size_t *n) {$/;" f file: +entries hash.h /^ size_t entries, size, newsize;$/;" m struct:__anon29 +entry hash.c /^ struct h_entry entry;$/;" m struct:h_node typeref:struct:h_node::h_entry file: +eval_expr expr.c /^struct val *eval_expr(struct expr *e) {$/;" f +eval_into expr.c /^void eval_into(struct expr *e, struct val *v) {$/;" f +eval_pop expr.c /^struct val *eval_pop(void) {$/;" f +eval_push expr.c /^void eval_push(struct expr *ex) {$/;" f +execute run.c /^struct val *execute(const struct op *op, struct val *arg) {$/;" f +expr expr.h /^ struct expr *expr;$/;" m union:expr::__anon27 typeref:struct:expr::__anon27::expr +expr expr.h /^struct expr {$/;" s +expr op.h /^ struct expr *expr;$/;" m union:op::__anon32 typeref:struct:op::__anon32::expr +expr sub.c /^ struct expr *expr;$/;" m struct:sub typeref:struct:sub::expr file: +expr_binop expr.c /^enum t_binop expr_binop(int c) {$/;" f +expr_end expr.c /^void expr_end(void) {$/;" f +expr_init expr.c /^void expr_init(void) {$/;" f +expr_pp expr.c /^void expr_pp(enum t_binop op, struct val *x, struct val *y) {$/;" f +ext val.h /^ IO *ext;$/;" m union:val::__anon40 +field list.h /^ struct val **field;$/;" m struct:li_whale typeref:struct:li_whale::val +file xmalloc.c /^ const char *file;$/;" m struct:node file: +fill re.c /^static void fill(unsigned char *v, int (*pred)(int)) {$/;" f file: +flags re.c /^ enum re_flags flags;$/;" m struct:my_regex typeref:enum:my_regex::re_flags file: +fp IO.c /^ FILE *fp;$/;" m struct:IO file: +free_expr expr.c /^void free_expr(struct expr *x) {$/;" f +get_expr expr.c /^struct expr *get_expr(struct op *op) {$/;" f +get_iobj expr.c /^struct expr *get_iobj(struct op *op) {$/;" f +get_list expr.c /^static struct expr *get_list(struct op *op, int null) {$/;" f file: +get_lval expr.c /^struct expr *get_lval(struct op *op) {$/;" f +get_value expr.c /^static struct expr *get_value(struct op *op, int null) {$/;" f file: +h_del hash.c /^int h_del(Hash *h, const void *key) {$/;" f +h_end hash.c /^void h_end(Hash *h) {$/;" f +h_entry hash.c /^struct h_entry {$/;" s file: +h_get hash.c /^int h_get(Hash *h, const void *key, void **res) {$/;" f +h_init hash.c /^void h_init($/;" f +h_nextkv hash.c /^int h_nextkv(Hash *h, void **k, void **v) {$/;" f +h_node hash.c /^struct h_node {$/;" s file: +h_put hash.c /^int h_put(Hash *h, void *key, void *val, int replace) {$/;" f +h_reset hash.c /^void h_reset(Hash *h) {$/;" f +hang hang.c /^void hang(void) {$/;" f +hash expr.h /^ t_strhash *hash;$/;" m union:expr::__anon26 +hash hash.c /^ size_t hash;$/;" m struct:h_entry file: +hash hash.h /^ size_t (*hash)(const void *, size_t);$/;" m struct:__anon29 +hash re.c /^static size_t hash(const void *s, size_t seed) {$/;" f file: +hash strhash.c /^ Hash hash;$/;" m struct:strhash file: +hash strhash.c /^static size_t hash(const void *p, size_t h) {$/;" f file: +hash variable.h /^ t_strhash *hash;$/;" m struct:__anon41 +hash venus.c /^static size_t hash(const void *p, size_t seed) {$/;" f file: +hp_expr transmogrify.c /^static int hp_expr(const struct expr *e) {$/;" f file: +id sub.c /^ size_t id;$/;" m struct:sub file: +inc_ludes inc.c /^const char *inc_ludes[] = INC_PREFIX_LIST;$/;" v +incr kork.c /^static dolphin *incr(dolphin *dp) {$/;" f file: +incr list.c /^static whale *incr(whale *wp) {$/;" f file: +indep re.c /^ } indep;$/;" m union:my_node typeref:struct:my_node::__anon17 file: +index run.h /^ size_t *index;$/;" m struct:Interp::__anon37 +index run.h /^ size_t *index;$/;" m struct:Interp::__anon38 +io_bufptr IO.c /^const char *io_bufptr(IO *io) {$/;" f +io_bufred IO.c /^int io_bufred(const IO *io) {$/;" f +io_clearerr IO.c /^void io_clearerr(IO *f) {$/;" f +io_close IO.c /^int io_close(IO *io) {$/;" f +io_cmppeek IO.c /^int io_cmppeek(IO *f, size_t o, const void *p, size_t n) {$/;" f +io_decr IO.c /^void io_decr(IO *io) {$/;" f +io_delete IO.c /^static void io_delete(IO *io) {$/;" f file: +io_end IO.c /^void io_end(void) {$/;" f +io_enter IO.c /^IO *io_enter(const char *name, FILE *fp, enum io_flags mode) {$/;" f +io_eof IO.c /^int io_eof(const IO *f) {$/;" f +io_err IO.c /^int io_err(const IO *f) {$/;" f +io_flags IO.h /^enum io_flags {$/;" g +io_flush IO.c /^int io_flush(IO *f) {$/;" f +io_fp IO.c /^FILE *io_fp(const IO *io) {$/;" f +io_getc IO.c /^int io_getc(IO *f) {$/;" f +io_getline IO.c /^size_t io_getline(IO *f, String *s) {$/;" f +io_incr IO.c /^IO *io_incr(IO *io) {$/;" f +io_init IO.c /^void io_init(void) {$/;" f +io_name IO.c /^const char *io_name(const IO *io, String *s) {$/;" f +io_open IO.c /^IO *io_open(const char *name, enum io_flags mode) {$/;" f +io_peek IO.c /^int io_peek(IO *f, size_t pos) {$/;" f +io_putc IO.c /^int io_putc(IO *f, int c) {$/;" f +io_read IO.c /^size_t io_read(IO *f, String *s, size_t n) {$/;" f +io_seek IO.c /^int io_seek(IO *f, long off, enum io_whence w) {$/;" f +io_tell IO.c /^long io_tell(IO *f) {$/;" f +io_unbuffer IO.c /^void io_unbuffer(IO *io) {$/;" f +io_whence IO.h /^enum io_whence {$/;" g +io_write IO.c /^size_t io_write(IO *f, const String *s) {$/;" f +io_write_m IO.c /^size_t io_write_m(IO *f, const void *p, size_t n) {$/;" f +io_write_s IO.c /^size_t io_write_s(IO *f, const char *s) {$/;" f +io_xcmp IO.c /^int io_xcmp(IO *f, size_t a, size_t b, size_t n) {$/;" f +iomatch re.c /^static size_t iomatch(const t_regex *base, const re_node *node, IO *s, size_t o) {$/;" f file: +iter hash.h /^ size_t iter;$/;" m struct:__anon29 +iterptr hash.h /^ struct h_node *iterptr;$/;" m struct:__anon29 typeref:struct:__anon29::h_node +kdp kork.h /^ struct ko_dolphin *kdp;$/;" m struct:kork typeref:struct:kork::ko_dolphin +key hash.c /^ void *key;$/;" m struct:h_entry file: +ko val.h /^ struct kork *ko;$/;" m struct:val typeref:struct:val::kork +ko_at kork.c /^int ko_at(const kork *k, size_t i) {$/;" f +ko_cat kork.c /^void ko_cat(kork *k, const kork *z) {$/;" f +ko_cat_c kork.c /^void ko_cat_c(kork *k, char c) {$/;" f +ko_cat_m kork.c /^void ko_cat_m(kork *k, const void *p, size_t n) {$/;" f +ko_chr kork.c /^size_t ko_chr(const kork *k, int c) {$/;" f +ko_cmp kork.c /^int ko_cmp(const kork *k1, const kork *k2) {$/;" f +ko_cpy kork.c /^void ko_cpy(kork *k, const kork *z) {$/;" f +ko_cpy_c kork.c /^void ko_cpy_c(kork *k, char c) {$/;" f +ko_cpy_m kork.c /^void ko_cpy_m(kork *k, const void *p, size_t n) {$/;" f +ko_cpy_s kork.c /^void ko_cpy_s(kork *k, const char *s) {$/;" f +ko_decouple kork.c /^void ko_decouple(kork *k) {$/;" f +ko_delete kork.c /^void ko_delete(kork *k) {$/;" f +ko_dolphin kork.h /^struct ko_dolphin {$/;" s +ko_dup kork.c /^kork *ko_dup(const kork *old) {$/;" f +ko_getline kork.c /^size_t ko_getline(IO *io, kork *k) {$/;" f +ko_grep kork.c /^void ko_grep(kork *k, int (*pred)(int)) {$/;" f +ko_lastchar kork.c /^int ko_lastchar(const kork *k) {$/;" f +ko_length kork.c /^size_t (ko_length)(const kork *k) {$/;" f +ko_length kork.h 60;" d +ko_lower kork.c /^void ko_lower(kork *k) {$/;" f +ko_new kork.c /^kork *ko_new(void) {$/;" f +ko_num kork.c /^void ko_num(kork *k, double d) {$/;" f +ko_ptr kork.c /^const char *ko_ptr(const kork *k) {$/;" f +ko_read kork.c /^size_t ko_read(IO *io, kork *k, size_t n) {$/;" f +ko_reverse kork.c /^void ko_reverse(kork *k) {$/;" f +ko_shift kork.c /^void ko_shift(kork *k, size_t n) {$/;" f +ko_shiftws kork.c /^void ko_shiftws(kork *k) {$/;" f +ko_str kork.c /^const String *ko_str(kork *k) {$/;" f +ko_szp kork.c /^const char *ko_szp(kork *k) {$/;" f +ko_trunc kork.c /^void ko_trunc(kork *k, size_t n) {$/;" f +ko_upper kork.c /^void ko_upper(kork *k) {$/;" f +ko_zero kork.c /^void (ko_zero)(kork *k) {$/;" f +ko_zero kork.h 61;" d +kork kork.c /^typedef struct kork kork;$/;" t typeref:struct:kork file: +kork kork.h /^struct kork {$/;" s +left expr.h /^ } left;$/;" m struct:expr typeref:union:expr::__anon27 +len re.c /^ size_t len;$/;" m struct:my_node::__anon18 file: +length Str.h /^ size_t length;$/;" m struct:__anon25 +length deparse.c /^ size_t length;$/;" m struct:__anon4 file: +length kork.h /^ size_t offset, length;$/;" m struct:kork +length list.h /^ size_t length, size;$/;" m struct:li_whale +length list.h /^ size_t offset, length;$/;" m struct:list +length mars.h /^ size_t size, length;$/;" m struct:mars +length run.h /^ size_t length, size;$/;" m struct:Interp::__anon36 +length strhash.c /^ size_t length;$/;" m struct:strx file: +length strhash.c /^ size_t length;$/;" m struct:strx_const file: +length text.h /^ size_t length, size;$/;" m struct:text +length variable.h /^ size_t size, length;$/;" m struct:__anon41 +length venus.c /^ size_t size, length;$/;" m struct:sorted file: +li_append list.c /^void li_append(struct list *k, const struct list *l) {$/;" f +li_at list.c /^struct val *li_at(const struct list *l, size_t i) {$/;" f +li_cmp list.c /^int li_cmp(const struct list *k, const struct list *l) {$/;" f +li_decouple list.c /^void li_decouple(struct list *l) {$/;" f +li_delete list.c /^void li_delete(struct list *l) {$/;" f +li_dup list.c /^struct list *li_dup(const struct list *k) {$/;" f +li_length list.c /^size_t (li_length)(const struct list *l) {$/;" f +li_length list.h 39;" d +li_new list.c /^struct list *li_new(void) {$/;" f +li_push list.c /^void li_push(struct list *l, struct val *v) {$/;" f +li_push_cpy list.c /^void li_push_cpy(struct list *l, const struct val *v) {$/;" f +li_reverse list.c /^void li_reverse(struct list *l) {$/;" f +li_shift list.c /^void li_shift(struct list *l, size_t n) {$/;" f +li_trunc list.c /^void li_trunc(struct list *l, size_t n) {$/;" f +li_whale list.h /^struct li_whale {$/;" s +li_zero list.c /^void (li_zero)(struct list *l) {$/;" f +li_zero list.h 40;" d +line op.h /^ size_t line;$/;" m struct:op +line xmalloc.c /^ unsigned line;$/;" m struct:node file: +list list.h /^struct list {$/;" s +list val.h /^ struct list *list;$/;" m union:val::__anon40 typeref:struct:val::__anon40::list +listE expr.h /^ listE$/;" e enum:t_expr +literE expr.h /^ literE,$/;" e enum:t_expr +liter_expr transmogrify.c /^static int liter_expr(const struct expr *const e) {$/;" f file: +literal re.c /^ } literal;$/;" m union:my_node typeref:struct:my_node::__anon18 file: +lwp list.h /^ struct li_whale *lwp;$/;" m struct:list typeref:struct:list::li_whale +m_end run.h /^ } m_end;$/;" m struct:Interp typeref:struct:Interp::__anon38 +m_start run.h /^ } m_start;$/;" m struct:Interp typeref:struct:Interp::__anon37 +ma_end mars.c /^void ma_end(struct mars *m) {$/;" f +ma_enter mars.c /^int ma_enter(struct mars *m, const String *key, struct op *value) {$/;" f +ma_exists mars.c /^int ma_exists(const struct mars *m, const String *key) {$/;" f +ma_find mars.c /^struct op *ma_find(const struct mars *m, String *key) {$/;" f +ma_init mars.c /^void ma_init(struct mars *m) {$/;" f +magic val.h /^ } magic;$/;" m struct:val typeref:union:val::__anon40 +main main.c /^int main(int argc, char **argv) {$/;" f +make_var deparse.c /^static void make_var(struct val *v) {$/;" f file: +mars mars.h /^struct mars {$/;" s +match re.c /^static size_t match(const t_regex *base, const re_node *node, const String *s, size_t o) {$/;" f file: +match run.h /^ } match;$/;" m struct:Interp typeref:struct:Interp::__anon36 +match_class re.c /^static int match_class(unsigned char c, const unsigned char *vec) {$/;" f file: +matches run.h /^ struct val *matches;$/;" m struct:Interp::__anon36 typeref:struct:Interp::__anon36::val +max re.c /^ size_t min, max;$/;" m struct:my_node::__anon19 file: +maximum re.c /^static size_t maximum(const size_t a, const size_t b) {$/;" f file: +mem_dup re.c /^static void *mem_dup(const void *p, size_t n, size_t m) {$/;" f file: +min re.c /^ size_t min, max;$/;" m struct:my_node::__anon19 file: +minimum re.c /^static size_t minimum(const size_t a, const size_t b) {$/;" f file: +minlen re.c /^ size_t minlen;$/;" m struct:my_regex file: +minlen re.c /^static size_t minlen(const re_node *node) {$/;" f file: +mode IO.c /^ enum io_flags mode;$/;" m struct:IO typeref:enum:IO::io_flags file: +my_mars_end main.c /^static void my_mars_end(void) {$/;" f file: +my_mars_end_flag main.c /^static int my_mars_end_flag;$/;" v file: +my_node re.c /^typedef union my_node {$/;" u file: +my_regex re.c /^struct my_regex {$/;" s file: +my_text_off main.c /^static void my_text_off(void) {$/;" f file: +my_venus_end main.c /^static void my_venus_end(void) {$/;" f file: +my_x_end run.c /^static void my_x_end(void) {$/;" f file: +n re.c /^ size_t n;$/;" m struct:my_node::__anon13 file: +n re.c /^ size_t n;$/;" m struct:my_node::__anon14 file: +n re.c /^ size_t n;$/;" m struct:my_node::__anon19 file: +name IO.c /^ char *name;$/;" m struct:IO file: +newsize hash.h /^ size_t entries, size, newsize;$/;" m struct:__anon29 +next IO.c /^ struct IO *prev, *next;$/;" m struct:IO typeref:struct:IO:: file: +next hash.c /^ struct h_node *next;$/;" m struct:h_node typeref:struct:h_node::h_node file: +next op.h /^ struct op *next;$/;" m struct:op typeref:struct:op::op +next re_block.c.h /^ struct block_node *next;$/;" m struct:block_node typeref:struct:block_node::block_node +next re_block.c.h /^ struct txt_node *next;$/;" m struct:txt_node typeref:struct:txt_node::txt_node +next xmalloc.c /^ struct node *prev, *next;$/;" m struct:node typeref:struct:node:: file: +nextchar opt.c /^static const char *nextchar;$/;" v file: +nfill re.c /^static void nfill(unsigned char *v, int (*pred)(int)) {$/;" f file: +nil kork.c /^static dolphin nil = {$/;" v file: +node xmalloc.c /^static struct node {$/;" s file: +nodes re_block.c.h /^ re_node nodes[BLOCK_MAGIC];$/;" m struct:block_node +notcomplex re.c /^static re_node **notcomplex(re_node **node, const re_node *end) {$/;" f file: +null mars.c /^static void null(struct mars **p, size_t n) {$/;" f file: +num val.h /^ double num;$/;" m struct:val +offoff kork.c /^static void offoff(kork *k) {$/;" f file: +offset Str.h /^ size_t offset;$/;" m struct:__anon25 +offset kork.h /^ size_t offset, length;$/;" m struct:kork +offset list.h /^ size_t offset, length;$/;" m struct:list +omgwtf_this_cant_be_happening zz.c /^void omgwtf_this_cant_be_happening(const char *file, unsigned long line) {$/;" f +op expr.h /^ struct op *op;$/;" m union:expr::__anon27 typeref:struct:expr::__anon27::op +op expr.h /^ int op;$/;" m struct:expr +op op.h /^ struct op *op;$/;" m union:op::__anon32 typeref:struct:op::__anon32::op +op op.h /^struct op {$/;" s +op_end op.c /^void op_end(struct op *op) {$/;" f +op_getop op.c /^void op_getop(struct op *p) {$/;" f +op_init op.c /^void op_init(struct op *op) {$/;" f +op_resolve compile.c /^static void op_resolve(struct op *o) {$/;" f file: +open_inc parse.c /^static IO *open_inc(const char *s, enum io_flags mode) {$/;" f file: +ops deparse.c /^ struct op **ops;$/;" m struct:__anon4 typeref:struct:__anon4::op file: +opt_arg opt.c /^const char *opt_arg;$/;" v +opt_err opt.c /^int opt_err;$/;" v +opt_get opt.c /^int opt_get(int argc, char *const *argv, const char *opts) {$/;" f +opt_ind opt.c /^int opt_ind;$/;" v +p re.c /^ size_t *p;$/;" m struct:parse_context file: +parse parse.c /^void parse(IO *f, struct text *text, size_t *line) {$/;" f +parse_context re.c /^struct parse_context {$/;" s file: +pending re.c /^ size_t start, end, pending;$/;" m struct:cap_state file: +pp_abs pp.c /^void pp_abs(struct val *v) {$/;" f +pp_abs pp.h /^DECL_PP1(pp_abs);$/;" v +pp_acos pp.c /^void pp_acos(struct val *v) {$/;" f +pp_acos pp.h /^DECL_PP1(pp_acos);$/;" v +pp_add pp.c /^void pp_add(struct val *v, struct val *b) {$/;" f +pp_add pp.h /^DECL_PP2(pp_add);$/;" v +pp_and pp.c /^void pp_and(struct val *v, struct val *b) {$/;" f +pp_and pp.h /^DECL_PP2(pp_and);$/;" v +pp_asin pp.c /^void pp_asin(struct val *v) {$/;" f +pp_asin pp.h /^DECL_PP1(pp_asin);$/;" v +pp_atan pp.c /^void pp_atan(struct val *v) {$/;" f +pp_atan pp.h /^DECL_PP1(pp_atan);$/;" v +pp_atan2 pp.c /^void pp_atan2(struct val *v) {$/;" f +pp_atan2 pp.h /^DECL_PP1(pp_atan2);$/;" v +pp_chr pp.c /^void pp_chr(struct val *v) {$/;" f +pp_chr pp.h /^DECL_PP1(pp_chr);$/;" v +pp_comma pp.c /^void pp_comma(struct val *v, struct val *b) {$/;" f +pp_comma pp.h /^DECL_PP2(pp_comma);$/;" v +pp_concat pp.c /^void pp_concat(struct val *v, struct val *b) {$/;" f +pp_concat pp.h /^DECL_PP2(pp_concat);$/;" v +pp_cos pp.c /^void pp_cos(struct val *v) {$/;" f +pp_cos pp.h /^DECL_PP1(pp_cos);$/;" v +pp_defined pp.c /^void pp_defined(struct val *v) {$/;" f +pp_defined pp.h /^DECL_PP1(pp_defined);$/;" v +pp_div pp.c /^void pp_div(struct val *v, struct val *b) {$/;" f +pp_div pp.h /^DECL_PP2(pp_div);$/;" v +pp_eof pp.c /^void pp_eof(struct val *v) {$/;" f +pp_eof pp.h /^DECL_PP1(pp_eof);$/;" v +pp_eq pp.c /^void pp_eq(struct val *v, struct val *b) {$/;" f +pp_eq pp.h /^DECL_PP2(pp_eq);$/;" v +pp_eq_n pp.c /^void pp_eq_n(struct val *v, struct val *b) {$/;" f +pp_eq_n pp.h /^DECL_PP2(pp_eq_n);$/;" v +pp_error pp.c /^void pp_error(struct val *v) {$/;" f +pp_error pp.h /^DECL_PP1(pp_error);$/;" v +pp_escape pp.c /^void pp_escape(struct val *v) {$/;" f +pp_escape pp.h /^DECL_PP1(pp_escape);$/;" v +pp_frombase pp.c /^void pp_frombase(struct val *v, struct val *b) {$/;" f +pp_frombase pp.h /^DECL_PP2(pp_frombase);$/;" v +pp_getc pp.c /^void pp_getc(struct val *v) {$/;" f +pp_getc pp.h /^DECL_PP1(pp_getc);$/;" v +pp_getenv pp.c /^void pp_getenv(struct val *v) {$/;" f +pp_getenv pp.h /^DECL_PP1(pp_getenv);$/;" v +pp_gets pp.c /^void pp_gets(struct val *v) {$/;" f +pp_gets pp.h /^DECL_PP1(pp_gets);$/;" v +pp_gt pp.c /^void pp_gt(struct val *v, struct val *b) {$/;" f +pp_gt pp.h /^DECL_PP2(pp_gt);$/;" v +pp_gt_n pp.c /^void pp_gt_n(struct val *v, struct val *b) {$/;" f +pp_gt_n pp.h /^DECL_PP2(pp_gt_n);$/;" v +pp_int pp.c /^void pp_int(struct val *v) {$/;" f +pp_int pp.h /^DECL_PP1(pp_int);$/;" v +pp_io pp.c /^void pp_io(struct val *v) {$/;" f +pp_io pp.h /^DECL_PP1(pp_io);$/;" v +pp_length pp.c /^void pp_length(struct val *v) {$/;" f +pp_length pp.h /^DECL_PP1(pp_length);$/;" v +pp_log pp.c /^void pp_log(struct val *v) {$/;" f +pp_log pp.h /^DECL_PP1(pp_log);$/;" v +pp_log10 pp.c /^void pp_log10(struct val *v) {$/;" f +pp_log10 pp.h /^DECL_PP1(pp_log10);$/;" v +pp_lower pp.c /^void pp_lower(struct val *v) {$/;" f +pp_lower pp.h /^DECL_PP1(pp_lower);$/;" v +pp_lt pp.c /^void pp_lt(struct val *v, struct val *b) {$/;" f +pp_lt pp.h /^DECL_PP2(pp_lt);$/;" v +pp_lt_n pp.c /^void pp_lt_n(struct val *v, struct val *b) {$/;" f +pp_lt_n pp.h /^DECL_PP2(pp_lt_n);$/;" v +pp_match pp.c /^void pp_match(struct val *v, struct val *b) {$/;" f +pp_match pp.h /^DECL_PP2(pp_match);$/;" v +pp_mod pp.c /^void pp_mod(struct val *v, struct val *b) {$/;" f +pp_mod pp.h /^DECL_PP2(pp_mod);$/;" v +pp_moend pp.c /^void pp_moend(struct val *v) {$/;" f +pp_moend pp.h /^DECL_PP1(pp_moend);$/;" v +pp_mostart pp.c /^void pp_mostart(struct val *v) {$/;" f +pp_mostart pp.h /^DECL_PP1(pp_mostart);$/;" v +pp_mult pp.c /^void pp_mult(struct val *v, struct val *b) {$/;" f +pp_mult pp.h /^DECL_PP2(pp_mult);$/;" v +pp_ne pp.c /^void pp_ne(struct val *v, struct val *b) {$/;" f +pp_ne pp.h /^DECL_PP2(pp_ne);$/;" v +pp_ne_n pp.c /^void pp_ne_n(struct val *v, struct val *b) {$/;" f +pp_ne_n pp.h /^DECL_PP2(pp_ne_n);$/;" v +pp_neg pp.c /^void pp_neg(struct val *v) {$/;" f +pp_neg pp.h /^DECL_PP1(pp_neg);$/;" v +pp_not pp.c /^void pp_not(struct val *v) {$/;" f +pp_not pp.h /^DECL_PP1(pp_not);$/;" v +pp_num pp.c /^void pp_num(struct val *v) {$/;" f +pp_num pp.h /^DECL_PP1(pp_num);$/;" v +pp_open pp.c /^void pp_open(struct val *v) {$/;" f +pp_open pp.h /^DECL_PP1(pp_open);$/;" v +pp_openr pp.c /^void pp_openr(struct val *v) {$/;" f +pp_openr pp.h /^DECL_PP1(pp_openr);$/;" v +pp_openw pp.c /^void pp_openw(struct val *v) {$/;" f +pp_openw pp.h /^DECL_PP1(pp_openw);$/;" v +pp_or pp.c /^void pp_or(struct val *v, struct val *b) {$/;" f +pp_or pp.h /^DECL_PP2(pp_or);$/;" v +pp_ord pp.c /^void pp_ord(struct val *v) {$/;" f +pp_ord pp.h /^DECL_PP1(pp_ord);$/;" v +pp_pop pp.c /^void pp_pop(struct val *v, struct val *b) {$/;" f +pp_pop pp.h /^DECL_PP2(pp_pop);$/;" v +pp_pow pp.c /^void pp_pow(struct val *v, struct val *b) {$/;" f +pp_pow pp.h /^DECL_PP2(pp_pow);$/;" v +pp_quote pp.c /^void pp_quote(struct val *v) {$/;" f +pp_quote pp.h /^DECL_PP1(pp_quote);$/;" v +pp_read pp.c /^void pp_read(struct val *v, struct val *b) {$/;" f +pp_read pp.h /^DECL_PP2(pp_read);$/;" v +pp_remove pp.c /^void pp_remove(struct val *v) {$/;" f +pp_remove pp.h /^DECL_PP1(pp_remove);$/;" v +pp_rename pp.c /^void pp_rename(struct val *v) {$/;" f +pp_rename pp.h /^DECL_PP1(pp_rename);$/;" v +pp_reverse pp.c /^void pp_reverse(struct val *v) {$/;" f +pp_reverse pp.h /^DECL_PP1(pp_reverse);$/;" v +pp_seek pp.c /^void pp_seek(struct val *v) {$/;" f +pp_seek pp.h /^DECL_PP1(pp_seek);$/;" v +pp_shift pp.c /^void pp_shift(struct val *v, struct val *b) {$/;" f +pp_shift pp.h /^DECL_PP2(pp_shift);$/;" v +pp_sin pp.c /^void pp_sin(struct val *v) {$/;" f +pp_sin pp.h /^DECL_PP1(pp_sin);$/;" v +pp_sqrt pp.c /^void pp_sqrt(struct val *v) {$/;" f +pp_sqrt pp.h /^DECL_PP1(pp_sqrt);$/;" v +pp_str pp.c /^void pp_str(struct val *v) {$/;" f +pp_str pp.h /^DECL_PP1(pp_str);$/;" v +pp_sub pp.c /^void pp_sub(struct val *v, struct val *b) {$/;" f +pp_sub pp.h /^DECL_PP2(pp_sub);$/;" v +pp_tan pp.c /^void pp_tan(struct val *v) {$/;" f +pp_tan pp.h /^DECL_PP1(pp_tan);$/;" v +pp_tell pp.c /^void pp_tell(struct val *v) {$/;" f +pp_tell pp.h /^DECL_PP1(pp_tell);$/;" v +pp_tobase pp.c /^void pp_tobase(struct val *v, struct val *b) {$/;" f +pp_tobase pp.h /^DECL_PP2(pp_tobase);$/;" v +pp_typeof pp.c /^void pp_typeof(struct val *v) {$/;" f +pp_typeof pp.h /^DECL_PP1(pp_typeof);$/;" v +pp_upper pp.c /^void pp_upper(struct val *v) {$/;" f +pp_upper pp.h /^DECL_PP1(pp_upper);$/;" v +prev IO.c /^ struct IO *prev, *next;$/;" m struct:IO typeref:struct:IO::IO file: +prev xmalloc.c /^ struct node *prev, *next;$/;" m struct:node typeref:struct:node::node file: +printinc main.c /^static void printinc(void) {$/;" f file: +ptr strhash.c /^ char *ptr;$/;" m struct:strx file: +ptr strhash.c /^ const char *ptr;$/;" m struct:strx_const file: +ptr xmalloc.c /^ void *ptr;$/;" m struct:node file: +quantifire re.c /^PRAZ(quantifire);$/;" v +randseed random.c /^void randseed(void) {$/;" f +randval random.c /^double randval(void) {$/;" f +rcache re.c /^static Hash rcache;$/;" v file: +re_backref re.c /^int re_backref(const t_regex *re, size_t i, size_t *a, size_t *z) {$/;" f +re_cabra re.c /^size_t re_cabra(const t_regex *re) {$/;" f +re_compile re.c /^t_regex *re_compile(const String *s) {$/;" f +re_decompile re.c /^void re_decompile(const t_regex *re, String *s) {$/;" f +re_dump re.c /^void re_dump(const t_regex *re, FILE *fp) {$/;" f +re_dup re.c /^t_regex *re_dup(t_regex *re) {$/;" f +re_end re.c /^void re_end(void) {$/;" f +re_flags re.c /^enum re_flags {$/;" g file: +re_free re.c /^void re_free(t_regex *re) {$/;" f +re_init re.c /^void re_init(void) {$/;" f +re_iomatch re.c /^int re_iomatch(t_regex *re, IO *io, size_t *ms, size_t *me) {$/;" f +re_match re.c /^int re_match(t_regex *re, const String *s, size_t *ms, size_t *me) {$/;" f +re_node re.c /^} re_node;$/;" t typeref:union:my_node file: +refs IO.c /^ size_t refs;$/;" m struct:IO file: +refs kork.h /^ size_t refs;$/;" m struct:ko_dolphin +refs list.h /^ size_t refs;$/;" m struct:li_whale +refs re.c /^ size_t refs;$/;" m struct:my_regex file: +refs sub.c /^ size_t refs;$/;" m struct:sub file: +reinit re.c /^static void reinit(t_regex *re) {$/;" f file: +rep re.c /^ } rep;$/;" m union:my_node typeref:struct:my_node::__anon19 file: +repbuf re.c /^ size_t *repbuf;$/;" m struct:my_regex file: +repets re.c /^ size_t repets;$/;" m struct:my_regex file: +resolve compile.c /^static void resolve(struct expr *e) {$/;" f file: +result run.h /^ struct val result;$/;" m struct:Interp typeref:struct:Interp::val +right expr.h /^ struct expr *right;$/;" m struct:expr typeref:struct:expr::expr +root re_block.c.h /^ struct block_node *root;$/;" m struct:__anon34 typeref:struct:__anon34::block_node +run run.c /^void run(const struct text *t, size_t argc, char **argv) {$/;" f +rx expr.h /^ t_regex *rx;$/;" m union:expr::__anon27 +s re.c /^ const String *s;$/;" m struct:parse_context file: +s_lastof main.c /^static char *s_lastof(const char *s, const char *set) {$/;" f file: +sanitycheck IO.c /^static void sanitycheck(enum io_flags m) {$/;" f file: +save_pair run.h /^} save_pair;$/;" t typeref:struct:__anon39 +seed hash.h /^ size_t seed;$/;" m struct:__anon29 +seen deparse.c /^} seen;$/;" v typeref:struct:__anon4 file: +select re.c /^ } select;$/;" m union:my_node typeref:struct:my_node::__anon20 file: +sh_delete strhash.c /^void sh_delete(t_strhash *sh) {$/;" f +sh_get strhash.c /^void *sh_get(t_strhash *sh, const char *key, size_t keylen) {$/;" f +sh_new strhash.c /^t_strhash *sh_new(void (*delv)(void *)) {$/;" f +sh_put strhash.c /^void sh_put(t_strhash *sh, const char *key, size_t keylen, void *val) {$/;" f +simplerep re.c /^static void simplerep(re_node *node, const re_node *const end) {$/;" f file: +siword re.c /^static int siword(int c) {$/;" f file: +size Str.h /^ size_t size;$/;" m struct:__anon25 +size deparse.c /^ size_t size;$/;" m struct:__anon4 file: +size hash.h /^ size_t entries, size, newsize;$/;" m struct:__anon29 +size list.h /^ size_t length, size;$/;" m struct:li_whale +size mars.h /^ size_t size, length;$/;" m struct:mars +size run.h /^ size_t length, size;$/;" m struct:Interp::__anon36 +size run.h /^ size_t size;$/;" m struct:Interp::__anon37 +size run.h /^ size_t size;$/;" m struct:Interp::__anon38 +size text.h /^ size_t length, size;$/;" m struct:text +size variable.h /^ size_t size, length;$/;" m struct:__anon41 +size venus.c /^ size_t size, length;$/;" m struct:sorted file: +size xmalloc.c /^ size_t size;$/;" m struct:node file: +skipline parse.c /^static void skipline(IO *f) {$/;" f file: +skipspace re.c /^static void skipspace(const String *const s, size_t *const p) {$/;" f file: +solid sub.c /^static void solid(struct expr *e) {$/;" f file: +sorted venus.c /^struct sorted {$/;" s file: +sp_error run.c /^static void sp_error(const save_pair *x, const save_pair *y) {$/;" f file: +sp_nop run.c /^static void sp_nop(save_pair *sp) {$/;" f file: +sp_writeback run.c /^static void sp_writeback(save_pair *sp) {$/;" f file: +stack stack.h 9;" d +stack_declare stack.h 12;" d +stack_define stack.h 33;" d +stack_func stack.h 10;" d +stack_store run.c /^void stack_store(struct val *target, const struct val *value) {$/;" f +stack_store_del run.c /^static void stack_store_del(struct val *target, struct val *value) {$/;" f file: +start re.c /^ re_node *start;$/;" m struct:my_regex file: +start re.c /^ size_t start, end, pending;$/;" m struct:cap_state file: +start text.h /^ struct op **start;$/;" m struct:text typeref:struct:text::op +str kork.h /^ String str;$/;" m struct:ko_dolphin +strhash strhash.c /^struct strhash {$/;" s file: +strx strhash.c /^struct strx {$/;" s file: +strx_const strhash.c /^struct strx_const {$/;" s file: +sub sub.c /^struct sub {$/;" s file: +sub val.h /^ struct sub *sub;$/;" m union:val::__anon40 typeref:struct:val::__anon40::sub +sub_decr sub.c /^void sub_decr(struct sub *p) {$/;" f +sub_expr sub.c /^struct expr *sub_expr(const struct sub *p) {$/;" f +sub_id sub.c /^size_t sub_id(const struct sub *p) {$/;" f +sub_incr sub.c /^struct sub *sub_incr(struct sub *p) {$/;" f +sub_new sub.c /^struct sub *sub_new(const struct expr *e) {$/;" f +subminlen re.c /^static size_t subminlen(const re_node *node, const re_node *end, size_t start) {$/;" f file: +sv_copy expr.c /^static void sv_copy(svalp *dst, const svalp *src) {$/;" f file: +sv_end expr.c /^static void sv_end(svalp *x) {$/;" f file: +sv_init expr.c /^static void sv_init(svalp *x) {$/;" f file: +svalp expr.c /^typedef struct val *svalp;$/;" t typeref:struct:val file: +symbolE expr.h /^ symbolE,$/;" e enum:t_expr +t_binop expr.h /^enum t_binop {$/;" g +t_block re_block.c.h /^} t_block;$/;" t typeref:struct:__anon34 +t_context expr.h /^} t_context;$/;" t typeref:struct:__anon28 +t_expr expr.h /^enum t_expr {$/;" g +t_func expr.h /^enum t_func {$/;" g +t_op op.h /^enum t_op {$/;" g +t_re_node re.c /^enum t_re_node {$/;" g file: +t_regex re.h /^typedef struct my_regex t_regex;$/;" t typeref:struct:my_regex +t_strhash strhash.h /^typedef struct strhash t_strhash;$/;" t typeref:struct:strhash +t_symbol expr.h /^enum t_symbol {$/;" g +t_vr_container variable.h /^} t_vr_container;$/;" t typeref:struct:__anon41 +t_vr_cookie variable.h /^typedef size_t t_vr_cookie;$/;" t +table hash.h /^ struct h_node **table;$/;" m struct:__anon29 typeref:struct:__anon29::h_node +table mars.h /^ struct mars **table;$/;" m struct:mars typeref:struct:mars::mars +table venus.h /^ Hash table;$/;" m struct:venus +target run.h /^ struct val *target;$/;" m struct:__anon39 typeref:struct:__anon39::val +tent expr.h /^ t_vr_cookie tent;$/;" m union:expr::__anon26 +text main.c /^static struct text text;$/;" v typeref:struct:text file: +text text.h /^struct text {$/;" s +text_1 text.c /^void text_1(struct text *p) {$/;" f +text_off text.c /^void text_off(struct text *p) {$/;" f +text_on text.c /^void text_on(struct text *p) {$/;" f +text_push text.c /^struct op *text_push(struct text *p, const struct op *src) {$/;" f +to_id deparse.c /^static void to_id(struct kork *k, size_t n) {$/;" f file: +told IO.c /^ long told;$/;" m struct:IO file: +trans_fold transmogrify.c /^void trans_fold(struct expr **e) {$/;" f +transmogrify transmogrify.c /^void transmogrify(struct text *code) {$/;" f +trysimpl re.c /^static void trysimpl(re_node *node) {$/;" f file: +txt op.h /^ String txt;$/;" m struct:op +txt_node re_block.c.h /^struct txt_node {$/;" s +txt_root re_block.c.h /^ struct txt_node *txt_root;$/;" m struct:__anon34 typeref:struct:__anon34::txt_node +type expr.h /^ enum t_expr type;$/;" m struct:expr typeref:enum:expr::t_expr +type op.h /^ enum t_op type;$/;" m struct:op typeref:enum:op::t_op +type val.h /^ enum val_cont type;$/;" m struct:val typeref:enum:val::val_cont +u_cmp strutil.c /^int u_cmp(const char *as, size_t al, const char *bs, size_t bl) {$/;" f +u_hash strutil.c /^size_t u_hash(const char *s, size_t l, size_t h) {$/;" f +undef expr.c /^static struct expr *undef(void) {$/;" f file: +unopE expr.h /^ unopE,$/;" e enum:t_expr +unoptimize main_opt.h /^ int unoptimize;$/;" m struct:Options +usage main.c /^static void usage(void) {$/;" f file: +used re_block.c.h /^ size_t used;$/;" m struct:block_node +v expr.h /^ } v;$/;" m struct:expr typeref:union:expr::__anon26 +v_cat val.c /^void v_cat(struct val *dst, struct val *src) {$/;" f +v_cat_c val.c /^void v_cat_c(struct val *v, char c) {$/;" f +v_cat_m val.c /^void v_cat_m(struct val *v, const void *p, size_t n) {$/;" f +v_cat_s val.c /^void v_cat_s(struct val *v, const String *s) {$/;" f +v_cmp_ls val.c /^int v_cmp_ls(struct val *v, struct val *b) {$/;" f +v_delete val.c /^void v_delete(struct val *v) {$/;" f +v_end val.c /^void v_end(struct val *v) {$/;" f +v_iniset val.c /^void v_iniset(struct val *dst, const struct val *src) {$/;" f +v_init val.c /^void v_init(struct val *v) {$/;" f +v_kork val.c /^struct kork *v_kork(struct val *v) {$/;" f +v_ok_num val.c /^void v_ok_num(struct val *v) {$/;" f +v_ok_str val.c /^void v_ok_str(struct val *v) {$/;" f +v_set val.c /^void v_set(struct val *dst, const struct val *src) {$/;" f +v_set_io val.c /^void v_set_io(struct val *v, IO *io) {$/;" f +v_set_m val.c /^void v_set_m(struct val *v, const void *p, size_t n) {$/;" f +v_set_n val.c /^void v_set_n(struct val *v, double d) {$/;" f +v_set_s val.c /^void v_set_s(struct val *v, const String *s) {$/;" f +v_set_sub val.c /^void v_set_sub(struct val *v, struct sub *s) {$/;" f +v_set_undef val.c /^void v_set_undef(struct val *v) {$/;" f +v_sptr val.c /^const char *v_sptr(struct val *v, size_t *l) {$/;" f +v_true val.c /^int v_true(const struct val *v) {$/;" f +v_undef val.c /^struct val *v_undef(void) {$/;" f +val expr.h /^ struct val *val;$/;" m union:expr::__anon26 typeref:struct:expr::__anon26::val +val val.h /^struct val {$/;" s +val_cont val.h /^enum val_cont {$/;" g +value hash.c /^ void *value;$/;" m struct:h_entry file: +varE expr.h /^ varE,$/;" e enum:t_expr +var_end main.c /^static void var_end(void) {$/;" f file: +varhashE expr.h /^ varhashE,$/;" e enum:t_expr +ve_end venus.c /^void ve_end(struct venus *v) {$/;" f +ve_enter venus.c /^void ve_enter(struct venus *v, const String *s, struct op *o) {$/;" f +ve_findnext venus.c /^struct op *ve_findnext(struct venus *v, const String *s, size_t line) {$/;" f +ve_findprev venus.c /^struct op *ve_findprev(struct venus *v, const String *s, size_t line) {$/;" f +ve_init venus.c /^void ve_init(struct venus *v) {$/;" f +ve_label venus.c /^const String *ve_label(struct venus *v, const struct op *op) {$/;" f +vec re.c /^ unsigned char *vec;$/;" m struct:my_node::__anon16 file: +vec re.c /^ unsigned char vec[CLASS_SIZE];$/;" m struct:my_node::__anon15 file: +venus venus.h /^struct venus {$/;" s +vpswap list.c /^static void vpswap(struct val **p, struct val **q) {$/;" f file: +vr_data variable.c /^void *(vr_data)(const t_vr_container *v, t_vr_cookie c) {$/;" f +vr_data variable.h 31;" d +vr_delete variable.c /^void vr_delete(t_vr_container *v) {$/;" f +vr_exists variable.c /^t_vr_cookie vr_exists(const t_vr_container *v, const char *key, size_t len) {$/;" f +vr_freeze variable.c /^void vr_freeze(t_vr_container *v) {$/;" f +vr_new variable.c /^t_vr_container *vr_new(void (*del)(void *)) {$/;" f +vr_register variable.c /^t_vr_cookie vr_register(t_vr_container *v, const char *key, size_t len, void *val) {$/;" f +walk deparse.c /^static int walk(const struct expr *e) {$/;" f file: +walk transmogrify.c /^static void walk(struct expr *e) {$/;" f file: +whale list.c /^typedef struct li_whale whale;$/;" t typeref:struct:li_whale file: +x re.c /^ } x;$/;" m union:my_node typeref:struct:my_node::__anon11 file: +xclip hash.c /^static size_t xclip(const Hash *h, const size_t hash_unc) {$/;" f file: +xdigits pp.c /^static const char xdigits[] = "0123456789" "abcdefghijklmnopqrstuvwxyz";$/;" v file: +xend xmalloc.c /^void xend(void) {$/;" f +xfree xmalloc.c /^void xfree(void *ptr) {$/;" f +xincentries hash.c /^static void xincentries(Hash *h) {$/;" f file: +xmalloc xmalloc.c /^void *(xmalloc)(size_t nmemb, size_t size, const char *file, unsigned line) {$/;" f +xmalloc xmalloc.h 12;" d +xrealloc xmalloc.c /^void *(xrealloc)(void *optr, size_t nmemb, const char *file, unsigned line) {$/;" f +xrealloc xmalloc.h 13;" d +xsh_delete main.c /^static void xsh_delete(void *sh) {$/;" f file: +xstep hash.c /^static void xstep(Hash *h) {$/;" f file: +xstrdup IO.c /^static char *xstrdup(const char *s) {$/;" f file: +xv_delete expr.c /^static void xv_delete(void *v) {$/;" f file: +xv_delete main.c /^static void xv_delete(void *v) {$/;" f file: +xval expr.c /^static int xval(int c) {$/;" f file:
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/text.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,34 @@ +#include "text.h" +#include "xmalloc.h" + +#include <stddef.h> + +enum {MAGIC = 42}; + +void text_on(struct text *p) { + p->start = xmalloc(p->size = MAGIC, sizeof *p->start); + p->start[p->length = 0] = NULL; +} + +void text_off(struct text *p) { + while (p->length) { + --p->length; + op_end(p->start[p->length]); + xfree(p->start[p->length]); + } + xfree(p->start); +} + +void text_1(struct text *p) { + while (p->length >= p->size - 1) { + p->start = xrealloc(p->start, p->size *= 2); + } +} + +struct op *text_push(struct text *p, const struct op *src) { + text_1(p); + p->start[p->length] = xmalloc(1, sizeof *p->start[p->length]); + *p->start[p->length++] = *src; + p->start[p->length] = NULL; + return p->start[p->length - 1]; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/text.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +text.o: text.c text.h op.h IO.h config.h Str.h expr.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/text.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,18 @@ +#ifndef TEXT_H_ +#define TEXT_H_ + +#include "op.h" + +#include <stddef.h> + +struct text { + size_t length, size; + struct op **start; +}; + +void text_on(struct text *); +void text_off(struct text *); +void text_1(struct text *); +struct op *text_push(struct text *, const struct op *); + +#endif /* TEXT_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/transmogrify.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,598 @@ +#include "config.h" +#include "Str.h" +#include "expr.h" +#include "kork.h" +#include "main_label.h" +#include "op.h" +#include "text.h" +#include "transmogrify.h" +#include "val.h" +#include "venus.h" +#include "xmalloc.h" +#include "zz.h" + +#include <ctype.h> +#include <math.h> +#include <stddef.h> +#include <assert.h> + +ATTR_PURE +static int liter_expr(const struct expr *const e) { + return + e->type == literE || + ( + e->type == symbolE && + e->op != S_ARG && e->op != S_ARGC && e->op != S_ARGV && + e->op != S_ERR && e->op != S_MATCH && e->op != S_RAND && + e->op != S_RESULT + ) || + ( + e->type == listE && + (e->right == NULL || liter_expr(e->right)) && + e->left.expr == NULL + ) + ; +} + +#define const_unop(op) \ +( \ + (op) == F_ABS || (op) == F_ACOS || (op) == F_ASIN || \ + (op) == F_ATAN || (op) == F_ATAN2 || (op) == F_CHR || \ + (op) == F_CHR || (op) == F_COS || (op) == F_DEFINED || \ + (op) == F_EXP || (op) == F_GETENV || (op) == F_INT || \ + (op) == F_IO || (op) == F_LENGTH || (op) == F_LOG || \ + (op) == F_LOG10 || (op) == F_LOWER || (op) == F_NEG || \ + (op) == F_NOT || (op) == F_NUM || (op) == F_ORD || \ + (op) == F_QUOTE || (op) == F_RE_ESC || (op) == F_REVERSE || \ + (op) == F_SIN || (op) == F_TAN || (op) == F_SQRT || \ + (op) == F_STR || (op) == F_TYPEOF || (op) == F_UPPER \ +) + +#define const_binop(op) \ +( \ + !((op) == B_SPOT || (op) == B_SQIGGLE || (op) == B_XMATCH) \ +) + +static int hp_expr(const struct expr *e) { + switch (e->type) { + case literE: + return 1; + + case varE: + return 1; + + case varhashE: + return hp_expr(e->right); + + case symbolE: + if (e->op != S_RAND) { + return 1; + } + return 0; + + case unopE: + if (!const_unop(e->op)) { + return 0; + } + return hp_expr(e->right); + + case binopE: + if (!const_binop(e->op)) { + return 0; + } + if (!hp_expr(e->left.expr)) { + return 0; + } + return hp_expr(e->right); + + case listE: + if (e->right) { + if (!hp_expr(e->right)) { + return 0; + } + if (!e->left.expr) { + return 1; + } + return hp_expr(e->left.expr); + } + return 1; + } + + NOTREACHED; +} + +void trans_fold(struct expr **e) { + struct val *v; + + switch ((*e)->type) { + case literE: + break; + + case varE: + break; + + case varhashE: + trans_fold(&(*e)->right); + break; + + case symbolE: + break; + + case unopE: + trans_fold(&(*e)->right); + if (liter_expr((*e)->right)) { + if ((*e)->op == F_NUL) { + v = eval_expr((*e)->right); + free_expr((*e)->right); + (*e)->right = xmalloc(1, sizeof *(*e)->right); + (*e)->right->type = literE; + (*e)->right->left.expr = (*e)->right->right = NULL; + (*e)->right->v.val = v_undef(); + TOLABEL(v); + if (((*e)->left.op = ve_findnext(&Venus, ko_str(v->ko), (*e)->left.bonus))) { + (*e)->op = F_CALL; + } else { + (*e)->op = F_HANG; + } + v_delete(v); + } else if (const_unop((*e)->op)) { + (*e)->v.val = eval_expr(*e); + free_expr((*e)->right); + (*e)->right = NULL; + (*e)->type = literE; + } + } else if ( + (*e)->right->type == unopE && + (*e)->op == (*e)->right->op && + ((*e)->op == F_STR || (*e)->op == F_NUM) + ) { + struct expr *const tmp = (*e)->right; + (*e)->right = (*e)->right->right; + tmp->right = NULL; + free_expr(tmp); + } + break; + + case binopE: + trans_fold(&(*e)->left.expr); + trans_fold(&(*e)->right); + if (liter_expr((*e)->left.expr) && liter_expr((*e)->right) && const_binop((*e)->op)) { + (*e)->v.val = eval_expr(*e); + free_expr((*e)->left.expr); + (*e)->left.expr = NULL; + free_expr((*e)->right); + (*e)->right = NULL; + (*e)->type = literE; + } else switch ((*e)->op) { + case B_INTERSECTION: + if ((*e)->left.expr->type == literE) { + V_NUM((*e)->left.expr->v.val); + if ((*e)->left.expr->v.val->num == 0.0) { + free_expr((*e)->left.expr); + (*e)->left.expr = NULL; + (*e)->op = F_NUM; + (*e)->type = unopE; + } + } else if ((*e)->right->type == literE) { + V_NUM((*e)->right->v.val); + if ((*e)->right->v.val->num == 0.0) { + free_expr((*e)->right); + (*e)->right = (*e)->left.expr; + (*e)->left.expr = NULL; + (*e)->op = F_NUM; + (*e)->type = unopE; + } + } + break; + + case B_TAIL: + if (hp_expr((*e)->left.expr)) { + struct expr *tmp; + + free_expr((*e)->left.expr); + tmp = *e; + *e = (*e)->right; + xfree(tmp); + } + break; + + case B_WORM: + if ((*e)->left.expr->type == literE) { + V_NUM((*e)->left.expr->v.val); + if ((*e)->left.expr->v.val->num == 0.0) { + free_expr((*e)->left.expr); + (*e)->left.expr = NULL; + (*e)->op = F_NEG; + (*e)->type = unopE; + } + } else if ((*e)->right->type == literE) { + V_NUM((*e)->right->v.val); + if ((*e)->right->v.val->num == 0.0) { + free_expr((*e)->right); + (*e)->right = (*e)->left.expr; + (*e)->left.expr = NULL; + (*e)->op = F_NUM; + (*e)->type = unopE; + } + } + break; + + case B_SHARK_FIN: + if ((*e)->left.expr->type == symbolE) { + if ((*e)->left.expr->op == S_EULER) { + free_expr((*e)->left.expr); + (*e)->left.expr = NULL; + (*e)->op = F_EXP; + (*e)->type = unopE; + } + } else if ((*e)->right->type == literE) { + V_NUM((*e)->right->v.val); + if ((*e)->right->v.val->num == 0.5) { + free_expr((*e)->right); + (*e)->right = (*e)->left.expr; + (*e)->left.expr = NULL; + (*e)->op = F_SQRT; + (*e)->type = unopE; + } + } + break; + + case B_FLATWORM: + if ((*e)->left.expr->type == literE) { + V_STR((*e)->left.expr->v.val); + if (!ko_length((*e)->left.expr->v.val->ko)) { + free_expr((*e)->left.expr); + (*e)->left.expr = NULL; + (*e)->op = F_STR; + (*e)->type = unopE; + } + } else if ((*e)->right->type == literE) { + V_STR((*e)->right->v.val); + if (!ko_length((*e)->right->v.val->ko)) { + free_expr((*e)->right); + (*e)->right = (*e)->left.expr; + (*e)->left.expr = NULL; + (*e)->op = F_STR; + (*e)->type = unopE; + } + } + break; + + case B_SQIGGLE: + case B_XMATCH: + if ((*e)->right->type == literE) { + t_regex *rx; + V_STR((*e)->right->v.val); + rx = re_compile(ko_str((*e)->right->v.val->ko)); + free_expr((*e)->right); + (*e)->right = (*e)->left.expr; + (*e)->left.rx = rx; + (*e)->op = F_MATCH; + (*e)->type = unopE; + } + break; + } + break; + + case listE: + if ((*e)->right) { + trans_fold(&(*e)->right); + if ((*e)->left.expr) { + trans_fold(&(*e)->left.expr); + } + } + break; + } +} + +#define SNAP(p) \ +do { \ + while ( \ + (p) && \ + (p)->type == OP_NOP && \ + (p) != (p)->next \ + ) { \ + (p) = (p)->next; \ + } \ +} while (0) + +static void walk(struct expr *e) { + for (;;) { + switch (e->type) { + case literE: + case symbolE: + return; + + case varE: + return; + + case varhashE: + e = e->right; + continue; + + case unopE: + if (e->op == F_CALL) { + SNAP(e->left.op); + if ( + e->left.op && + e->left.op->type == OP_RETURN && + hp_expr(e->right) && + liter_expr(e->left.op->arg) + ) { + free_expr(e->right); + e->right = NULL; + switch (e->left.op->arg->type) { + case literE: + e->v.val = v_undef(); + v_set(e->v.val, e->left.op->arg->v.val); + e->type = literE; + break; + + case symbolE: + e->op = e->left.op->arg->op; + e->type = symbolE; + break; + + case listE: + assert(!e->left.op->arg->left.expr && !e->left.op->arg->right); + e->type = listE; + break; + + default: + NOTREACHED; + } + e->left.expr = NULL; + return; + } + } + e = e->right; + continue; + + case binopE: + walk(e->left.expr); + e = e->right; + continue; + + case listE: + if (e->right) { + if (e->left.expr) { + walk(e->left.expr); + } + e = e->right; + continue; + } + return; + } + } +} + +void transmogrify(struct text *code) { + size_t i; + struct op *hang = NULL; + + for (i = 0; i < code->length; ++i) { + struct op *op = code->start[i]; + + switch (op->type) { + case OP_CALL: + case OP_CALL_DYN: + case OP_CLOSE: + case OP_EXIT: + case OP_FLUSH: + case OP_GOBACK: + case OP_GOTO: + case OP_IF: + case OP_RESET: + case OP_RETURN: + case OP_SYSTEM: + case OP_THROW: + trans_fold(&op->arg); + break; + + case OP_ASSIGN: + trans_fold(&op->arg); + if (!op->arh.expr) { + if (hp_expr(op->arg)) { + free_expr(op->arg); + op->arg = NULL; + op->type = OP_NOP; + } + } else { + trans_fold(&op->arh.expr); + if ( + op->arh.expr->type == varE && + op->arg->type == binopE && + op->arg->left.expr->type == varE && + op->arh.expr->v.val == op->arg->left.expr->v.val + ) { + struct expr *const tmp = op->arg; + op->arh.expr->op = op->arg->op; + op->arg = op->arg->right; + xfree(tmp->left.expr); + xfree(tmp); + op->type = OP_MODIFY; + } else if (op->arg->type == literE) { + op->type = OP_SET_VAL; + } + } + break; + + case OP_CALL_BACK: + case OP_MODIFY: + trans_fold(&op->arh.expr); + trans_fold(&op->arg); + break; + + case OP_PRINT: + case OP_PUTC: + case OP_TEMP: + trans_fold(&op->arg); + if (op->arh.expr) { + trans_fold(&op->arh.expr); + } + break; + + default: + break; + } + } + + for (i = 0; i < code->length; ++i) { + struct op *op = code->start[i]; + + switch (op->type) { + case OP_CALL_BACK: + if (liter_expr(op->arh.expr)) { + struct val *v; + + v = eval_expr(op->arh.expr); + TOLABEL(v); + free_expr(op->arh.expr); + if ((op->arh.op = ve_findprev(&Venus, ko_str(v->ko), op->line))) { + op->type = OP_CALL; + } else { + free_expr(op->arg); + op->arg = NULL; + op->type = OP_HANG; + hang = op; + } + v_end(v); + xfree(v); + } + break; + + case OP_CALL_DYN: + case OP_GOBACK: + case OP_GOTO: + if (liter_expr(op->arg)) { + struct val *v; + + v = eval_expr(op->arg); + TOLABEL(v); + free_expr(op->arg); + op->arg = NULL; + if ((op->arh.op = (op->type == OP_GOBACK ? ve_findprev : ve_findnext)(&Venus, ko_str(v->ko), op->line))) { + if (op->type == OP_CALL_DYN) { + op->type = OP_CALL; + op->arg = xmalloc(1, sizeof *op->arg); + op->arg->left.expr = op->arg->right = NULL; + op->arg->type = literE; + op->arg->v.val = v_undef(); + } else { + op->next = op->arh.op; + op->arh.op = NULL; + op->type = OP_NOP; + } + } else { + op->type = OP_HANG; + hang = op; + } + v_end(v); + xfree(v); + } + break; + + case OP_HANG: + hang = op; + break; + + case OP_IF: + if (liter_expr(op->arg)) { + struct val *v; + + v = eval_expr(op->arg); + if (v_true(v)) { + op->next = op->arh.op; + } + v_delete(v); + op->type = OP_NOP; + op->arh.expr = NULL; + free_expr(op->arg); + op->arg = NULL; + } + break; + + case OP_PRINT: + if ( + op->arg->type == literE && + ( + ( + op->arg->v.val->type == V_STR_K && + ko_length(op->arg->v.val->ko) == 0 + ) || + op->arg->v.val->type == V_UNDEF + ) + ) { + op->type = OP_NOP; + free_expr(op->arg); + op->arg = NULL; + if (op->arh.expr) { + free_expr(op->arh.expr); + op->arh.expr = NULL; + } + break; + } + if ( + op->arh.expr && + op->arh.expr->type == symbolE && + op->arh.expr->op == S_STDOUT + ) { + free_expr(op->arh.expr); + op->arh.expr = NULL; + } + break; + + default: + break; + } + } + + if (!hang) { + struct op tmp; + + tmp.type = OP_HANG; + tmp.arg = tmp.arh.expr = NULL; + tmp.next = NULL; + St_init(&tmp.txt); + St_clear(&tmp.txt); + tmp.line = -1; + + hang = text_push(code, &tmp); + } + + for (i = 0; i < code->length; ++i) { + struct op *op = code->start[i]; + + SNAP(op->next); + if (op->type == OP_IF) { + SNAP(op->arh.op); + } else if (op->type == OP_CALL) { + SNAP(op->arh.op); + if (!op->arh.op) { + struct expr *tmp = xmalloc(1, sizeof *tmp); + tmp->type = binopE; + tmp->op = B_TAIL; + tmp->left.expr = op->arg; + tmp->right = xmalloc(1, sizeof *tmp->right); + tmp->right->type = literE; + tmp->right->v.val = v_undef(); + tmp->right->left.expr = tmp->right->right = NULL; + op->arg = tmp; + op->type = OP_EXIT; + trans_fold(&op->arg); + } + } + + if (op == op->next) { + op->next = hang; + } + if (OP_1ARG_P(op->type)) { + walk(op->arg); + } else if (OP_2ARG_P(op->type)) { + if (op->arh.expr) { + walk(op->arh.expr); + } + walk(op->arg); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/transmogrify.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,3 @@ +transmogrify.o: transmogrify.c config.h Str.h expr.h op.h IO.h re.h \ + stack.h xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h \ + main_label.h mars.h venus.h hash.h text.h transmogrify.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/transmogrify.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,10 @@ +#ifndef TRANSMOGRIFY_H_ +#define TRANSMOGRIFY_H_ + +#include "expr.h" +#include "text.h" + +void trans_fold(struct expr **); +void transmogrify(struct text *); + +#endif /* TRANSMOGRIFY_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/try/poly.lhs Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +poly.poly \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/try/poly.poly Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,94 @@ + # /* [ <!-- */ include <stdio.h> /*[0]0 \ + #{\ +`""""true \\#{"\n#"}; \ + \ +if [ -n "$ZSH_VERSION" ]; then \ + \ + echo exec echo I\'m a zsh script.; \ + \ +elif [ -n "$BASH_VERSION" ]; then \ + \ + echo exec echo I\'m a bash script.; \ +else \ + echo exec echo I\'m a sh script.; \ +fi`; #\ +BEGIN{print"I'm a ",(("I'm a ploki program.\n")[0?0:0]?0:0)?"Ruby" :"Perl", " program.\n"; exit; } + #\ +END{} + #\ +%q~ + +set dummy =0; puts [list "I'm" "a" "tcl" "script."]; exit + +all: ; @echo "I'm a Makefile." \ + #)*/ +/*: */ enum {a, b}; \ + \ +static int c99(void) { + + #ifndef __cplusplus /*[0]0) bah */ + +unused1: if ((enum {b, a})0) \ + (void)0; + #endif + +unused2: return a; \ +} \ +static int trigraphs(void) { \ + \ + return sizeof "??!" == 2; \ +} \ +char X; \ + \ +int main(void) { \ + \ + struct X { \ + \ + char a[2]; \ + };\ + if (sizeof(X) != 1) { \ + \ +printf("I'm a C++ program (trigraphs %sabled).\n", \ + \ + trigraphs() ? "en" : "dis");\ + \ +}else if (1//**/2 + + +)unused3 : { ; \ + printf("I'm a C program (C%s, trigraphs %sabled).\n", \ + c99() ? "89 with // comments" : "99", \ + trigraphs() ? "en" : "dis"); \ + } else { \ + printf("I'm a C program (C89, trigraphs %sabled).\n", \ + trigraphs() ? "en" : "dis"); \ + } \ + return 0; \ +} /* + # \ + +> main :: IO () -- -- \ +> main = putStr "I'm a Literate Haskell program.\n" + + # \ +]>++++++++[<+++++++++>-]<+.>>++++[<++++++++++>-]<-.[-]>++++++++++ \ +[<+++++++++++>-]<-.>>++++[<++++++++>-]<.>>++++++++++[<++++++++++> \ +-]<- - -.<.>+.->>++++++++++[<+++++++++++>-]<++++.<.>>>++++++++++[ \ +<++++++++++>-]<+++++.<<<<+.->>>>- - -.<+++.- - -<++.- ->>>>>+++++ \ ++++++[<+++++++++++>-]<- - -.<<<<<.<+++.>>>.<<<-.- ->>>>+.<.<.<<.> \ +++++++++++++++.[-]++++++++++"""` + # \ +print "I'm a Python program."; """[-][--><html><head> +<!--:--><title>I'm a HTML page</title></head><body> +<!--:--><h1>I'm a <marquee><blink>horrible HTML</blink></marquee> page</h1> +<!--:--><script language="JavaScript"> +<!--: # \ +setTimeout( // \ + function () { // \ + document.body.innerHTML = "<h1>I'm a javascript-generated HTML page</h1>"; // \ + }, 10000); // \ +//--> +</script><!--: \ +</body></html><!-- } # \ +say "I'm a Perl6 program", try { " ($?PUGS_VERSION)" } // "", "."; # """ # */ + #define FOO ]-->~
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/try/t.pk Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,22 @@ +LET n "tmp.txt" +LET fh @APERS #<n "W+"#> +IF @NOT fh + WUNT \FEHL "open: " _ n _ ": " _ \! _ " + END 1 +END IF +WUNT fh "zomg +IF @SUCH #<fh 0#> + WUNT \FEHL "seek: " _ n _ ": " _ \! _ " + END 1 +FI +LET s fh . @NEG 1 +IF @ERR-P fh + WUNT \FEHL "read: " _ n _ ": " _ \! _ " + END 1 +FI +CLAUDS fh +IF \_ + WUNT \FEHL "close: " _ n _ ": " _ \! _ " + END 1 +END IF +s
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/val.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,219 @@ +#include "config.h" +#include "IO.h" +#include "Str.h" +#include "val.h" +#include "xmalloc.h" + +#include <stdlib.h> +#include <assert.h> + +void v_init(struct val *v) { + v->ko = ko_new(); + v->type = V_UNDEF; +} + +void v_end(struct val *v) { + assert(v != NULL); + V_xxx_OFF(v); + ko_delete(v->ko); + v->type = V_UNDEF; +} + +int v_cmp_ls(struct val *v, struct val *b) { + if (V_LIST_P(v) && V_LIST_P(b)) { + return li_cmp(v->magic.list, b->magic.list); + } + V_STR(v); + V_STR(b); + return ko_cmp(v->ko, b->ko); +} + +void v_ok_str(struct val *v) { + if (V_STR_P(v)) { + return; + } + + if (V_EXT_P(v)) { + ko_cpy_s(v->ko, io_name(v->magic.ext, NULL)); + } else if (V_LIST_P(v)) { + size_t i; + struct list *li = v->magic.list; + struct val *cur; + + ko_zero(v->ko); + for (i = 0; i < li_length(li); ++i) { + cur = li_at(li, i); + V_STR(cur); + ko_cat(v->ko, cur->ko); + } + } else if (V_NUM_P(v)) { + ko_num(v->ko, v->num); + } else if (V_SUB_P(v)) { + v_ok_num(v); + ko_num(v->ko, v->num); + } else { + ko_zero(v->ko); + } + v->type |= V_STR_K; +} + +void v_ok_num(struct val *v) { + if (V_NUM_P(v)) { + return; + } + + if (V_EXT_P(v)) { + v->num = __LINE__; + } else if (V_SUB_P(v)) { + v->num = sub_id(v->magic.sub); + } else if (V_LIST_P(v)) { + size_t i; + + v->num = 0.0; + for (i = 0; i < li_length(v->magic.list); ++i) { + V_NUM(li_at(v->magic.list, i)); + v->num += li_at(v->magic.list, i)->num; + } + } else if (V_STR_P(v)) { + v->num = strtod(ko_szp(v->ko), NULL); + } else { + v->num = 0.0; + } + v->type |= V_NUM_K; +} + +int v_true(const struct val *v) { + if (V_EXT_P(v) || V_SUB_P(v)) { + return 1; + } + if (V_LIST_P(v)) { + return li_length(v->magic.list) != 0; + } + if (V_STR_P(v)) { + return ko_length(v->ko) != 0 && (ko_length(v->ko) > 1u || ko_at(v->ko, 0) != '0'); + } + if (V_NUM_P(v)) { + return v->num != 0.0; + } + return 0; +} + +void v_iniset(struct val *dst, const struct val *src) { + v_init(dst); + v_set(dst, src); +} + +void v_set(struct val *dst, const struct val *src) { + assert(src != NULL); + + V_xxx_OFF(dst); + dst->type = V_UNDEF; + + if (V_SUB_P(src)) { + dst->magic.sub = sub_incr(src->magic.sub); + dst->type |= V_SUB_K; + } else if (V_EXT_P(src)) { + dst->magic.ext = io_incr(src->magic.ext); + dst->type |= V_EXT_K; + } else if (V_LIST_P(src)) { + dst->magic.list = li_dup(src->magic.list); + dst->type |= V_LIST_K; + } + + if (V_STR_P(src)) { + ko_cpy(dst->ko, src->ko); + dst->type |= V_STR_K; + } + if (V_NUM_P(src)) { + dst->num = src->num; + dst->type |= V_NUM_K; + } +} + +void v_set_n(struct val *v, double d) { + V_xxx_OFF(v); + v->num = d; + v->type = V_NUM_K; +} + +void v_set_s(struct val *v, const String *s) { + V_xxx_OFF(v); + ko_cpy_m(v->ko, St_ptr(s), St_len(s)); + v->type = V_STR_K; +} + +void v_set_m(struct val *v, const void *p, size_t n) { + V_xxx_OFF(v); + ko_cpy_m(v->ko, p, n); + v->type = V_STR_K; +} + +void v_set_io(struct val *v, IO *io) { + V_xxx_OFF(v); + v->magic.ext = io_incr(io); + v->type = V_EXT_K; +} + +void v_set_sub(struct val *v, struct sub *s) { + V_xxx_OFF(v); + v->magic.sub = sub_incr(s); + v->type = V_SUB_K; +} + +void v_set_undef(struct val *v) { + V_xxx_OFF(v); + v->type = V_UNDEF; +} + +void v_cat(struct val *dst, struct val *src) { + if (V_LIST_P(dst) && V_LIST_P(src)) { + li_append(dst->magic.list, src->magic.list); + return; + } + + V_STR(src); + V_STR(dst); + V_xxx_OFF(dst); + ko_cat(dst->ko, src->ko); + dst->type = V_STR_K; +} + +void v_cat_m(struct val *v, const void *p, size_t n) { + V_STR(v); + V_xxx_OFF(v); + ko_cat_m(v->ko, p, n); + v->type = V_STR_K; +} + +void v_cat_s(struct val *v, const String *s) { + v_cat_m(v, St_ptr(s), St_len(s)); +} + +void v_cat_c(struct val *v, char c) { + v_cat_m(v, &c, 1); +} + +struct val *v_undef(void) { + struct val *v; + v = xmalloc(1, sizeof *v); + v_init(v); + return v; +} + +void v_delete(struct val *v) { + v_end(v); + xfree(v); +} + +const char *v_sptr(struct val *v, size_t *l) { + V_STR(v); + if (l) { + *l = ko_length(v->ko); + } + return ko_ptr(v->ko); +} + +struct kork *v_kork(struct val *v) { + V_STR(v); + return v->ko; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/val.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +val.o: val.c config.h IO.h Str.h val.h kork.h list.h sub.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/val.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,80 @@ +#ifndef VAL_H_ +#define VAL_H_ + +#include "config.h" +#include "IO.h" +#include "Str.h" +#include "kork.h" +#include "list.h" +#include "sub.h" + +enum val_cont { + V_UNDEF = 0, + V_STR_K = 1, + V_NUM_K = V_STR_K << 1, + V_EXT_K = V_NUM_K << 1, + V_SUB_K = V_EXT_K << 1, + V_LIST_K = V_SUB_K << 1 +}; + +struct val { + enum val_cont type; + union { + IO *ext; + struct sub *sub; + struct list *list; + } magic; + struct kork *ko; + double num; +}; + +void v_init(struct val *); +void v_end(struct val *); +int v_cmp_ls(struct val *, struct val *); +void v_ok_str(struct val *); +void v_ok_num(struct val *); +int v_true(const struct val *); +void v_iniset(struct val *, const struct val *); +void v_set(struct val *, const struct val *); +void v_set_n(struct val *, double); +void v_set_s(struct val *, const String *); +void v_set_m(struct val *, const void *, size_t); +void v_set_undef(struct val *); +void v_set_io(struct val *, IO *); +void v_set_sub(struct val *, struct sub *); +void v_cat(struct val *, struct val *); +void v_cat_s(struct val *, const String *); +void v_cat_m(struct val *, const void *, size_t); +void v_cat_c(struct val *, char); +struct val *v_undef(void); +void v_delete(struct val *); + +const char *v_sptr(struct val *, size_t *); +struct kork *v_kork(struct val *); + +#define V_STR_P(v) ((v)->type & V_STR_K) +#define V_NUM_P(v) ((v)->type & V_NUM_K) +#define V_EXT_P(v) ((v)->type & V_EXT_K) +#define V_SUB_P(v) ((v)->type & V_SUB_K) +#define V_LIST_P(v) ((v)->type & V_LIST_K) + +#define V_STR(v) if (V_STR_P(v)); else v_ok_str(v) +#define V_NUM(v) if (V_NUM_P(v)); else v_ok_num(v) + +#define V_xxx_OFF(v) \ +do { \ + if (V_EXT_P(v)) { \ + io_decr((v)->magic.ext); \ + (v)->type &= ~V_EXT_K; \ + } else if (V_SUB_P(v)) { \ + sub_decr((v)->magic.sub); \ + (v)->type &= ~V_SUB_K; \ + } else if (V_LIST_P(v)) { \ + li_delete((v)->magic.list); \ + (v)->type &= ~V_LIST_K; \ + } \ +} while (0) + +#define RINT(x) ((x) + ((x) < 0.0 ? -.5 : .5)) + +#endif /* VAL_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/variable.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,72 @@ +#include "config.h" +#include "Str.h" +#include "strhash.h" +#include "variable.h" +#include "xmalloc.h" + +#include <assert.h> + +enum {MAGIC = 23}; + +static void delcookie(void *c) { + xfree(c); +} + +t_vr_container *vr_new(void (*del)(void *)) { + t_vr_container *v = xmalloc(1, sizeof *v); + v->data = xmalloc(v->size = MAGIC, sizeof *v->data); + v->length = 0; + v->del = del; + v->hash = sh_new(delcookie); + return v; +} + +void vr_delete(t_vr_container *v) { + assert(v != NULL); + if (v->hash) { + vr_freeze(v); + } + while (v->length) { + --v->length; + if (v->del) { + v->del(v->data[v->length]); + } + } + xfree(v->data); + xfree(v); +} + +t_vr_cookie vr_exists(const t_vr_container *v, const char *key, size_t len) { + t_vr_cookie *c; + assert(v->hash != NULL); + return (c = sh_get(v->hash, key, len)) ? *c : VR_NO_COOKIE; +} + +t_vr_cookie vr_register(t_vr_container *v, const char *key, size_t len, void *val) { + t_vr_cookie *cookie; + + assert(v->hash != NULL); + assert(sh_get(v->hash, key, len) == NULL); + + if (v->length >= v->size) { + v->data = xrealloc(v->data, v->size *= 2); + } + + cookie = xmalloc(1, sizeof *cookie); + v->data[*cookie = v->length++] = val; + sh_put(v->hash, key, len, cookie); + + return *cookie; +} + +void vr_freeze(t_vr_container *v) { + assert(v->hash != NULL); + sh_delete(v->hash); + v->hash = NULL; +} + +void *(vr_data)(const t_vr_container *v, t_vr_cookie c) { + assert(v->hash == NULL); + assert(c < v->length); + return v->data[c]; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/variable.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +variable.o: variable.c config.h Str.h strhash.h variable.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/variable.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,34 @@ +#ifndef VARIABLE_H_ +#define VARIABLE_H_ + +#include "config.h" +#include "strhash.h" + +#include <stddef.h> + +typedef size_t t_vr_cookie; +#define VR_NO_COOKIE ((size_t)-1) + +typedef struct { + void **data; + size_t size, length; + t_strhash *hash; + void (*del)(void *); +} t_vr_container; + +t_vr_container *vr_new(void (*)(void *)); +void vr_delete(t_vr_container *); + +t_vr_cookie vr_exists(const t_vr_container *, const char *, size_t); +t_vr_cookie vr_register(t_vr_container *, const char *, size_t, void *); + +void vr_freeze(t_vr_container *); + +ATTR_PURE +void *vr_data(const t_vr_container *, t_vr_cookie); + +#if !DEBUG_P +#define vr_data(vc, c) ((vc)->data[c]) +#endif + +#endif /* VARIABLE_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/venus.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,146 @@ +#include "Str.h" +#include "hash.h" +#include "op.h" +#include "venus.h" +#include "xmalloc.h" +#include "zz.h" + +#include <stddef.h> +#include <stdio.h> +#include <string.h> + +enum {MAGIC = 23}; + +struct sorted { + size_t size, length; + struct op **array; +}; + +static size_t hash(const void *p, size_t seed) { + return St_hash(p, seed); +} + +static int compar(const void *a, const void *b) { + return St_cmp(a, b); +} + +static void delk(void *k) { + St_clear(k); + xfree(k); +} + +static void delv(void *v) { + xfree(((struct sorted *)v)->array); + xfree(v); +} + +void ve_init(struct venus *v) { + h_init(&v->table, hash, compar, delk, delv); +} + +void ve_end(struct venus *v) { + h_end(&v->table); +} + +void ve_enter(struct venus *v, const String *s, struct op *o) { + struct sorted *x; + void *tmp; + size_t a, z; + + if (h_get(&v->table, s, &tmp) == H_NOENT) { + String *label; + x = xmalloc(1, sizeof *x); + x->array = xmalloc(x->size = MAGIC, sizeof *x->array); + x->array[0] = o; + x->length = 1; + label = xmalloc(1, sizeof *label); + St_init(label); + St_cpy(label, s); + h_put(&v->table, label, x, 1); + return; + } + x = tmp; + + for (a = 0, z = x->length; a < z; ) { + if (x->array[(a + z) / 2]->line < o->line) { + a = (a + z) / 2 + 1u; + } else if (x->array[(a + z) / 2]->line > o->line) { + z = (a + z) / 2; + } else { + NOTREACHED; + } + } + + if (x->length >= x->size) { + x->array = xrealloc(x->array, x->size *= 2); + } + memmove(x->array + a + 1u, x->array + a, x->length - a); + x->array[a] = o; + x->length++; +} + +struct op *ve_findnext(struct venus *v, const String *s, size_t line) { + struct sorted *x; + void *tmp; + size_t a, z; + + if (h_get(&v->table, s, &tmp) == H_NOENT) { + return NULL; + } + x = tmp; + + for (a = 0, z = x->length; a < z; ) { + if (x->array[(a + z) / 2]->line < line) { + a = (a + z) / 2 + 1u; + } else if (x->array[(a + z) / 2]->line > line) { + z = (a + z) / 2; + } else { + a = (a + z) / 2 + 1u; + break; + } + } + + return x->array[a % x->length]; +} + +struct op *ve_findprev(struct venus *v, const String *s, size_t line) { + struct sorted *x; + void *tmp; + size_t a, z; + + if (h_get(&v->table, s, &tmp) == H_NOENT) { + return NULL; + } + x = tmp; + + for (a = 0, z = x->length; a < z; ) { + if (x->array[(a + z) / 2]->line < line) { + a = (a + z) / 2 + 1u; + } else if (x->array[(a + z) / 2]->line > line) { + z = (a + z) / 2; + } else { + a = (a + z) / 2; + break; + } + } + a += x->length - 1u; + return x->array[a % x->length]; +} + +const String *ve_label(struct venus *v, const struct op *op) { + void *key, *value; + + h_reset(&v->table); + while (h_nextkv(&v->table, &key, &value) == H_OK) { + const struct sorted *x = value; + size_t i; + + for (i = 0; i < x->length; ++i) { + if (x->array[i] == op) { + return key; + } + } + } + + return NULL; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/venus.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,2 @@ +venus.o: venus.c Str.h config.h hash.h op.h IO.h expr.h re.h stack.h \ + xmalloc.h strhash.h val.h kork.h list.h sub.h variable.h venus.h zz.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/venus.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,19 @@ +#ifndef VENUS_H_ +#define VENUS_H_ + +#include "Str.h" +#include "hash.h" +#include "op.h" + +struct venus { + Hash table; +}; + +void ve_init(struct venus *); +void ve_end(struct venus *); +void ve_enter(struct venus *, const String *, struct op *); +struct op *ve_findnext(struct venus *, const String *, size_t); +struct op *ve_findprev(struct venus *, const String *, size_t); +const String *ve_label(struct venus *, const struct op *); + +#endif /* VENUS_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/version.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,5 @@ +#line 1 "version.c.in" +#include "version.h" + +const char *Version = +"0.6.5.1";
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/version.c.in Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,4 @@ +#line 1 "version.c.in" +#include "version.h" + +const char *Version =
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/version.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +version.o: version.c version.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/version.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,6 @@ +#ifndef VERSION_H_ +#define VERSION_H_ + +extern const char *Version; + +#endif /* VERSION_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/xmalloc.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,168 @@ +#include "config.h" +#include "main.h" +#include "xmalloc.h" + +#include <assert.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#ifdef DEBUG_MALLOC + #define IF_DB(x) x +#else + #define IF_DB(x) +#endif + +static struct node { + void *ptr; + struct node *prev, *next; + size_t size; + #if DEBUG_P + const char *file; + unsigned line; + #endif +} *Root; + +#if 0 +int xdump(void) { + struct node *p; + + fprintf(stderr, ":%p\n", Root); + for (p = Root; p; p = p->next) { + fprintf(stderr, "\\<%p [%p]%p %p>\n", p->prev, p, p->ptr, p->next); + assert(p != p->next); + } + fprintf(stderr, "\n"); + return 0; +} +#endif + +void xend(void) { + struct node *p; + + while ((p = Root)) { +#if DEBUG_P + unsigned char *ptr; + for (ptr = p->ptr; memcmp(ptr, &p, sizeof p); ++ptr) + ; + ptr += sizeof p; + fprintf(stderr, "%s: autofreeing pointer %p (%p) from %s:%u\n", Prog, p->ptr, (void *)ptr, p->file, p->line); +#else + fprintf(stderr, "%s: autofreeing pointer %p\n", Prog, p->ptr); +#endif + free(p->ptr); + assert(Root != p->next); + Root = p->next; + free(p); + } +} + +#define XFACTOR(size) ((sizeof (struct node *) - 1) / (size) + 1u) + +#if DEBUG_P +void *(xrealloc)(void *optr, size_t nmemb, const char *file, unsigned line) { +#else +void *xrealloc(void *optr, size_t nmemb) { +#endif + struct node *p; + size_t k; + size_t size; + unsigned char *r; + void *ptr; + + assert(optr != NULL); + + memcpy(&p, (unsigned char *)optr - sizeof Root, sizeof p); + size = p->size; + k = XFACTOR(size) * size; + if (!(ptr = realloc(p->ptr, size * nmemb + k))) { + fprintf(stderr, "%s: realloc(%p, %lu): %s\n", Prog, ptr, (unsigned long)(nmemb * size), strerror(errno)); + abort(); + } + r = (unsigned char *)ptr + k; + #if DEBUG_P + IF_DB(fprintf(stderr, "%s: xrealloc(%zu): %p (%p) from %s:%u -> %p (%p) from %s:%u\n", Prog, nmemb, p->ptr, optr, p->file, p->line, ptr, r, file, line)); + p->file = file; + p->line = line; + #endif + p->ptr = ptr; + return r; +} + +#if DEBUG_P +void *(xmalloc)(size_t nmemb, size_t size, const char *file, unsigned line) { +#else +void *xmalloc(size_t nmemb, size_t size) { +#endif + struct node *p; + size_t k; + unsigned char *r; + + if ((p = malloc(sizeof *p))) { + k = XFACTOR(size) * size; + if (!(p->ptr = malloc(size * nmemb + k))) { + free(p); + goto failure; + } + } else failure: { + fprintf(stderr, "%s: malloc(%lu): %s\n", Prog, (unsigned long)(nmemb * size), strerror(errno)); + abort(); + } + #if DEBUG_P + memset(p->ptr, 'U', k); + #endif + r = (unsigned char *)p->ptr + k; + memcpy(r - sizeof Root, &p, sizeof p); + p->size = size; + p->prev = NULL; + p->next = Root; + #if DEBUG_P + p->file = file; + p->line = line; + IF_DB(fprintf(stderr, "%s: xmalloc(%zu, %zu): %p (%p) from %s:%u\n", Prog, nmemb, size, p->ptr, r, file, line)); + #endif + if (Root) { + Root->prev = p; + } + Root = p; + return r; +} + +#if 0 +#if DEBUG_P +void *(xcalloc)(size_t nmemb, size_t size, const char *file, unsigned line) { + void *const p = xmalloc(nmemb, size, file, line); +#else +void *xcalloc(size_t nmemb, size_t size) { + void *const p = xmalloc(nmemb, size); +#endif + memset(p, '\0', nmemb * size); + return p; +} +#endif + +void xfree(void *ptr) { + struct node *p; + + if (!ptr) + return; + memcpy(&p, (unsigned char *)ptr - sizeof Root, sizeof p); + assert(p != NULL); + DEBUG(memset((unsigned char *)ptr - sizeof Root, 'F', sizeof Root)); + + if (p->next) { + p->next->prev = p->prev; + } + if (p->prev) { + p->prev->next = p->next; + } else { + assert(p == Root); + Root = Root->next; + } + #if DEBUG_P + IF_DB(fprintf(stderr, "%s: xfree(): %p (%p) from %s:%u\n", Prog, p->ptr, ptr, p->file, p->line)); + #endif + free(p->ptr); + free(p); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/xmalloc.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +xmalloc.o: xmalloc.c config.h main.h xmalloc.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/xmalloc.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,20 @@ +#ifndef XMALLOC_H_ +#define XMALLOC_H_ + +#include "config.h" + +#include <stddef.h> + +void xend(void); +#if DEBUG_P +void *xmalloc(size_t, size_t, const char *, unsigned); +void *xrealloc(void *, size_t, const char *, unsigned); +#define xmalloc(n, m) xmalloc(n, m, __FILE__, __LINE__) +#define xrealloc(p, n) xrealloc(p, n, __FILE__, __LINE__) +#else +void *xmalloc(size_t, size_t); +void *xrealloc(void *, size_t); +#endif +void xfree(void *); + +#endif /* XMALLOC_H_ */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/zz.c Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,10 @@ +#include "zz.h" +#include "main.h" + +#include <stdio.h> +#include <stdlib.h> + +void omgwtf_this_cant_be_happening(const char *file, unsigned long line) { + fprintf(stderr, "%s: %s:%lu: error message\n", Prog, file, line); + abort(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/zz.depend Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,1 @@ +zz.o: zz.c zz.h config.h main.h
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ploki/zz.h Fri Dec 20 22:04:38 2013 +0000 @@ -0,0 +1,11 @@ +#ifndef ZZ_H_ +#define ZZ_H_ + +#include "config.h" + +ATTR_NORETURN +void omgwtf_this_cant_be_happening(const char *, unsigned long); + +#define NOTREACHED omgwtf_this_cant_be_happening(__FILE__, __LINE__) + +#endif /* ZZ_H_ */