diff --git a/1991/ant/.entry.json b/1991/ant/.entry.json index 4291db44e..0925e9583 100644 --- a/1991/ant/.entry.json +++ b/1991/ant/.entry.json @@ -41,6 +41,30 @@ "display_via_github" : true, "entry_text" : "original source code" }, + { + "file_path" : "deobfuscated/ant-c89.c", + "inventory_order" : 140, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided deobfuscated code converted from K&R" + }, + { + "file_path" : "deobfuscated/ant.c", + "inventory_order" : 140, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided deobfuscated code" + }, + { + "file_path" : "deobfuscated/Makefile", + "inventory_order" : 150, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided Makefile for deobfuscated code" + }, { "file_path" : "1991_ant.tar.bz2", "inventory_order" : 1415926535, diff --git a/1991/ant/.gitignore b/1991/ant/.gitignore index 587fcf92c..209eb3816 100644 --- a/1991/ant/.gitignore +++ b/1991/ant/.gitignore @@ -3,6 +3,8 @@ *.dSYM ant ant.alt +ant.alt2 +ant.alt2-c89 ant.orig hill indent diff --git a/1991/ant/Makefile b/1991/ant/Makefile index 162b91643..b8612e1e5 100644 --- a/1991/ant/Makefile +++ b/1991/ant/Makefile @@ -119,8 +119,8 @@ OBJ= ${PROG}.o DATA= README.md TARGET= ${PROG} hill mole # -ALT_OBJ= ${PROG}.alt.o -ALT_TARGET= ${PROG}.alt +ALT_OBJ= ${PROG}.alt.o deobfuscated/${PROG}.o +ALT_TARGET= ${PROG}.alt deobfuscated/${PROG} ################# @@ -151,6 +151,29 @@ mole: ${PROG}.c hill alt: data ${ALT_TARGET} @${TRUE} +${PROG}.alt: ${PROG}.alt.c hill + ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} + +# We keep the deobfuscated source code and Makefile in deobfuscated/, and use +# that Makefile but then move the compiled programs to the entry's directory to +# keep both directories clean and to allow the deobfuscated Makefile and code to +# be used but not require the user to do: +# +# ./deobfuscated/ant +# ./deobfuscated/ant-c89 +# +# but rather simply: +# +# ./ant.alt2 +# ./ant.alt2-c89 +# +# The alt2 is because this is the secondary alt. +deobfuscated/${PROG}: deobfuscated/${PROG}.c deobfuscated/${PROG}-c89.c + ${MAKE} -C deobfuscated ant + ${MV} -vf deobfuscated/ant ant.alt2 + ${MAKE} -C deobfuscated ant-c89 + ${MV} -vf deobfuscated/ant-c89 ant.alt2-c89 + # data files # data: ${DATA} @@ -217,7 +240,7 @@ clean: clobber: clean ${RM} -f ${TARGET} ${ALT_TARGET} - ${RM} -rf *.dSYM + ${RM} -rf *.dSYM ant.alt ant.alt2 ant.alt2-c89 @-if [ -e sandwich ]; then \ ${RM} -f sandwich; \ echo 'ate sandwich'; \ diff --git a/1991/ant/README.md b/1991/ant/README.md index 04cce98b2..ca830f3fb 100644 --- a/1991/ant/README.md +++ b/1991/ant/README.md @@ -4,8 +4,9 @@ make all ``` -There is an [alternate version](#alternate-code) that might feel a bit more -familiar to vi(m) users. +There is an alternate version that might feel a bit more familiar to vi(m) +users. Additionally, the author provided deobfuscated versions including one for +C89. See [Alternate code](#alternate-code) below. ## To use: @@ -33,12 +34,20 @@ program exit without doing anything. ## Alternate code: -This version changes the commands slightly so that to go to the first column you -should enter `0`, to go to the last column you should enter `$`, to quit you -should enter `q`, to go back a word you should enter `b` and to go forwards a -word you should enter `w`. Also, and perhaps most useful, rather than having to -hit ctrl-L (form-feed, `\f`) to get back to command mode you can use the usual -ESC (`\x1b`). +The author provided us with deobfuscated versions including one for C89. The two +C files in `deobfuscated`, +[deobfuscated/ant.c](%%REPO_URL%%/1991/ant/deobfuscated/ant.c) and +[deobfuscated/ant-c89.c](%%REPO_URL%%/1991/ant/deobfuscated/ant-c89.c) and the +[deobfuscated/Makefile](%%REPO_URL%%/1991/ant/deobfuscated/Makefile) will allow +you to look at them and compile them if you wish. These are exactly like the +original in every way, including in use, except they are deobfuscated. + +The other version, [ant.alt.c](%%REPO_URL%%/1991/ant/ant.alt.c) changes the +commands slightly so that to go to the first column you should enter `0`, to go +to the last column you should enter `$`, to quit you should enter `q`, to go +back a word you should enter `b` and to go forwards a word you should enter `w`. +Also, and perhaps most useful, rather than having to hit ctrl-L (form-feed, +`\f`) to get back to command mode you can use the usual ESC (`\x1b`). These will make it slightly less unwieldy for those familiar with vi(m); the rest was unchanged. @@ -53,8 +62,10 @@ rest was unchanged. ### Alternate use: -Use `ant.alt` as you would `ant` above with the changes in the input keys. See -the author's remarks for the remaining keys. +For the deobfuscated versions, use `ant.alt2` and `ant.alt2-c89` as you would +`ant` above; for the other one, `ant.alt`, use it as you would `ant` above but +with the changes in the input keys described above. See the author's remarks for +the remaining commands. ## Judges' remarks: diff --git a/1991/ant/deobfuscated/Makefile b/1991/ant/deobfuscated/Makefile new file mode 100644 index 000000000..e99ba8050 --- /dev/null +++ b/1991/ant/deobfuscated/Makefile @@ -0,0 +1,34 @@ +# +# Anthony's Editor +# +# IOCCC 1991 +# +# Winner Best Utility +# + +CFLAGS = -Os -Wno-deprecated-non-prototype + +all: build + +build: ant ant-c89 + +clean: + -rm -f ant ant-c89 + +# NOTE: some systems may need: +# +# old SYS V: +# cc ${CFLAGS} -DMODE=0600 -DBUF=32767 -o ant ant.c -lcurses +# ATARI ST: +# cc -DMODE=0 -DBUF=32767 -o ant.ttp ant.c curses.a +# PC class: +# wcl -mc -DMODE=0 -DBUF=32767 ant.c curses.lib +# +# This older version may generate lots of warnings with newer compilers. +# +ant: ant.c + ${CC} ${CFLAGS} -DMODE=0600 -DBUF=32767 ant.c -o $@ -lcurses -ltermcap + +# Mostly cosmetic changes to read like ANSI C 89. +ant-c89: ant-c89.c + ${CC} ${CFLAGS} -DMODE=0600 ant-c89.c -o $@ -lcurses -ltermcap diff --git a/1991/ant/deobfuscated/ant-c89.c b/1991/ant/deobfuscated/ant-c89.c new file mode 100644 index 000000000..142c5f425 --- /dev/null +++ b/1991/ant/deobfuscated/ant-c89.c @@ -0,0 +1,371 @@ +/* + * Anthony's Editor + * + * Public Domain 1991, 2023 by Anthony Howe. All rights released. + */ + +#include +#include +#include +#include +#include + +#ifndef BUF +# define BUF (USHRT_MAX) +#endif + +#define TABWIDTH 8 +#define TABSTOP(col) (TABWIDTH - ((col) & (TABWIDTH-1))) + +static int done; +static int row, col; +static int here, page, epage; +static char buf[BUF]; +static char *ebuf; +static char *gap = buf; +static char *egap; +static char *filename; + +/* + * The following assertions must be maintained. + * + * o buf <= gap <= egap <= ebuf + * If gap == egap then the buffer is full. + * + * o point = ptr(here) and point < gap or egap <= point + * + * o page <= here < epage + * + * o 0 <= here <= pos(ebuf) <= BUF + * + * + * Memory representation of the file: + * + * low buf -->+----------+ + * | front | + * | of file | + * gap -->+----------+<-- character not in file + * | hole | + * egap -->+----------+<-- character in file + * | back | + * | of file | + * high ebuf -->+----------+<-- character not in file + * + * + * point & gap + * + * The Point is the current cursor position while the Gap is the + * position where the last edit operation took place. The Gap is + * ment to be the cursor but to avoid shuffling characters while + * the cursor moves it is easier to just move a pointer and when + * something serious has to be done then you move the Gap to the + * Point. + */ + +char * +ptr(int offset) +{ + if (offset < 0) { + return buf; + } + return buf+offset + (buf+offset < gap ? 0 : egap-gap); +} + +int +pos(char *pointer) +{ + return pointer-buf - (pointer < egap ? 0 : egap-gap); +} + +void +top(void) +{ + here = 0; +} + +void +bottom(void) +{ + epage = here = pos(ebuf); +} + +void +quit(void) +{ + done = 1; +} + +void +movegap(void) +{ + char *p = ptr(here); + while (p < gap) { + *--egap = *--gap; + } + while (egap < p) { + *gap++ = *egap++; + } + here = pos(egap); +} + +int +prevline(int offset) +{ + char *p; + while (buf < (p = ptr(--offset)) && *p != '\n') { + ; + } + return buf < p ? ++offset : 0; +} + +int +nextline(int offset) +{ + char *p; + while ((p = ptr(offset++)) < ebuf && *p != '\n') { + ; + } + return p < ebuf ? offset : pos(ebuf); +} + +int +adjust(int offset, int column) +{ + char *p; + int i = 0; + while ((p = ptr(offset)) < ebuf && *p != '\n' && i < column) { + i += *p == '\t' ? TABSTOP(i) : 1; + ++offset; + } + return offset; +} + +void +display(void) +{ + char *p; + int i, j; + if (here < page) { + page = prevline(here); + } + if (epage <= here) { + page = nextline(here); + i = page == pos(ebuf) ? LINES-2 : LINES; + while (0 < i--) { + page = prevline(page-1); + } + } + move(0, 0); + clrtobot(); + i = j = 0; + epage = page; + for (;;) { + if (here == epage) { + row = i; + col = j; + } + p = ptr(epage); + if (LINES <= i || ebuf <= p) { + break; + } + if (*p != '\r') { + /* Handle tab expansion ourselves. Differences + * between historical Curses and NCurses 2021 + * WRT tab handling I can't suss just yet. + * + * Historical Curses addch() would handle tab + * expansion as I recall while (current 2021) + * NCurses does not by default it seems. + */ + if (*p == '\t') { + j += TABSTOP(j); + move(i, j); + } else { + addch(*p); + j++; + } + } + if (*p == '\n' || COLS <= j) { + ++i; + j = 0; + } + ++epage; + } + if (++i < LINES) { + mvaddstr(i, 0, "~EOF~"); + } + move(row, col); + refresh(); +} + +void +redraw(void) +{ + clear(); + display(); +} + +void +left(void) +{ + if (0 < here) { + --here; + } +} + +void +right(void) +{ + if (here < pos(ebuf)) { + ++here; + } +} + +void +up(void) +{ + here = adjust(prevline(prevline(here)-1), col); +} + +void +down(void) +{ + here = adjust(nextline(here), col); +} + +void +lnbegin(void) +{ + here = prevline(here); +} + +void +lnend(void) +{ + here = nextline(here); + left(); +} + +void +wleft(void) +{ + char *p; + while (!isspace(*(p = ptr(here))) && buf < p) { + --here; + } + while (isspace(*(p = ptr(here))) && buf < p) { + --here; + } +} + +void +pgdown(void) +{ + page = here = prevline(epage-1); + while (0 < row--){ + down(); + } + epage = pos(ebuf); +} + +void +pgup(void) +{ + int i = LINES; + while (0 < --i) { + page = prevline(page-1); + up(); + } +} + +void +wright(void) +{ + char *p; + while (!isspace(*(p = ptr(here))) && p < ebuf) { + ++here; + } + while (isspace(*(p = ptr(here))) && p < ebuf) { + ++here; + } +} + +void +insert(void) +{ + int ch; + movegap(); + while ((ch = getch()) != '\e' && ch != '\f') { + if (ch == '\b') { + if (buf < gap) { + --gap; + } + } else if (gap < egap) { + *gap++ = ch == '\r' ? '\n' : ch; + } + here = pos(egap); + display(); + } +} + +void +delete(void) +{ + movegap(); + if (egap < ebuf) { + here = pos(++egap); + } +} + +void +file(void) +{ + int i; + int j = here; + here = 0; + movegap(); + (void) write(i = creat(filename, MODE), egap, (int)(ebuf-egap)); + (void) close(i); + here = j; +} + +static char key[] = "hjklHJKL[]tbixWRQ"; + +static void (*func[])(void) = { + left, down, up, right, + wleft, pgdown, pgup, wright, + lnbegin, lnend, top, bottom, + insert, delete, file, redraw, quit, movegap +}; + +int +main(int argc, char **argv) +{ + int ch, i; + egap = ebuf = buf + BUF; + if (argc < 2) { + return 2; + } + initscr(); + raw(); + noecho(); + idlok(stdscr, 1); + if (0 < (i = open(filename = *++argv, 0))) { + gap += read(i, buf, BUF); + if (gap < buf) { + gap = buf; + } + (void) close(i); + } + top(); + while (!done) { + display(); + ch = getch(); + for (i = 0; key[i] != '\0' && ch != key[i]; i++) { + ; + } + (*func[i])(); + } + endwin(); + return 0; +} diff --git a/1991/ant/deobfuscated/ant.c b/1991/ant/deobfuscated/ant.c new file mode 100644 index 000000000..d8748adc6 --- /dev/null +++ b/1991/ant/deobfuscated/ant.c @@ -0,0 +1,364 @@ +/* + * ae.c Anthony's Editor IOCCC '91 + * + * Public Domain 1991 by Anthony Howe. All rights released. + */ + +#include +#include +#include +#include +#include + + +int done; +int row, col; +int idx, page, epage; +char buf[BUF]; +char *ebuf; +char *gap = buf; +char *egap; +char *filename; + +/* + * The following assertions must be maintained. + * + * o buf <= gap <= egap <= ebuf + * If gap == egap then the buffer is full. + * + * o point = ptr(idx) and point < gap or egap <= point + * + * o page <= idx < epage + * + * o 0 <= idx <= pos(ebuf) <= BUF + * + * + * Memory representation of the file: + * + * low buf -->+----------+ + * | front | + * | of file | + * gap -->+----------+<-- character not in file + * | hole | + * egap -->+----------+<-- character in file + * | back | + * | of file | + * high ebuf -->+----------+<-- character not in file + * + * + * point & gap + * + * The Point is the current cursor position while the Gap is the + * position where the last edit operation took place. The Gap is + * ment to be the cursor but to avoid shuffling characters while + * the cursor moves it is easier to just move a pointer and when + * something serious has to be done then you move the Gap to the + * Point. + */ + +int adjust(); +int nextline(); +int pos(); +int prevline(); +char *ptr(); + +void bottom(); +void delete(); +void display(); +void down(); +void file(); +void insert(); +void left(); +void lnbegin(); +void lnend(); +void movegap(); +void pgdown(); +void pgup(); +void redraw(); +void right(); +void quit(); +void top(); +void up(); +void wleft(); +void wright(); + +char key[] = "hjklHJKL[]tbixWRQ"; +void (*func[])() = { + left, down, up, right, + wleft, pgdown, pgup, wright, + lnbegin, lnend, top, bottom, + insert, delete, file, redraw, quit, movegap +}; + +char * +ptr(offset) +int offset; +{ + if (offset < 0) + return (buf); + return (buf+offset + (buf+offset < gap ? 0 : egap-gap)); +} + +int +pos(pointer) +char *pointer; +{ + return (pointer-buf - (pointer < egap ? 0 : egap-gap)); +} + +void +top() +{ + idx = 0; +} + +void +bottom() +{ + epage = idx = pos(ebuf); +} + +void +quit() +{ + done = 1; +} + +void +redraw() +{ + clear(); + display(); +} + +void +movegap() +{ + char *p = ptr(idx); + while (p < gap) + *--egap = *--gap; + while (egap < p) + *gap++ = *egap++; + idx = pos(egap); +} + +int +prevline(offset) +int offset; +{ + char *p; + while (buf < (p = ptr(--offset)) && *p != '\n') + ; + return (buf < p ? ++offset : 0); +} + +int +nextline(offset) +int offset; +{ + char *p; + while ((p = ptr(offset++)) < ebuf && *p != '\n') + ; + return (p < ebuf ? offset : pos(ebuf)); +} + +int +adjust(offset, column) +int offset, column; +{ + char *p; + int i = 0; + while ((p = ptr(offset)) < ebuf && *p != '\n' && i < column) { + i += *p == '\t' ? 8-(i&7) : 1; + ++offset; + } + return (offset); +} + +void +left() +{ + if (0 < idx) + --idx; +} + +void +right() +{ + if (idx < pos(ebuf)) + ++idx; +} + +void +up() +{ + idx = adjust(prevline(prevline(idx)-1), col); +} + +void +down() +{ + idx = adjust(nextline(idx), col); +} + +void +lnbegin() +{ + idx = prevline(idx); +} + +void +lnend() +{ + idx = nextline(idx); + left(); +} + +void +wleft() +{ + char *p; + while (!isspace(*(p = ptr(idx))) && buf < p) + --idx; + while (isspace(*(p = ptr(idx))) && buf < p) + --idx; +} + +void +pgdown() +{ + page = idx = prevline(epage-1); + while (0 < row--) + down(); + epage = pos(ebuf); +} + +void +pgup() +{ + int i = LINES; + while (0 < --i) { + page = prevline(page-1); + up(); + } +} + +void +wright() +{ + char *p; + while (!isspace(*(p = ptr(idx))) && p < ebuf) + ++idx; + while (isspace(*(p = ptr(idx))) && p < ebuf) + ++idx; +} + +void +insert() +{ + int ch; + movegap(); + while ((ch = getch()) != '\f') { + if (ch == '\b') { + if (buf < gap) + --gap; + } else if (gap < egap) { + *gap++ = ch == '\r' ? '\n' : ch; + } + idx = pos(egap); + display(); + } +} + +void +delete() +{ + movegap(); + if (egap < ebuf) + idx = pos(++egap); +} + +void +file() +{ + int i; + int j = idx; + idx = 0; + movegap(); + write(i = creat(filename, MODE), egap, (int)(ebuf-egap)); + close(i); + idx = j; +} + +void +display() +{ + char *p; + int i, j; + if (idx < page) + page = prevline(idx); + if (epage <= idx) { + page = nextline(idx); + i = page == pos(ebuf) ? LINES-2 : LINES; + while (0 < i--) + page = prevline(page-1); + } + move(0, 0); + i = j = 0; + epage = page; + while (1) { + if (idx == epage) { + row = i; + col = j; + } + p = ptr(epage); + if (LINES <= i || ebuf <= p) + break; + if (*p != '\r') { + addch(*p); + j += *p == '\t' ? 8-(j&7) : 1; + } + if (*p == '\n' || COLS <= j) { + ++i; + j = 0; + } + ++epage; + } + clrtobot(); + if (++i < LINES) + mvaddstr(i, 0, "<< EOF >>"); + move(row, col); + refresh(); +} + +int +main(argc, argv) +int argc; +char **argv; +{ + int ch, i; + egap = ebuf = buf + BUF; + if (argc < 2) + return (2); + initscr(); + raw(); + noecho(); + idlok(stdscr, 1); + if (0 < (i = open(filename = *++argv, 0))) { + gap += read(i, buf, BUF); + if (gap < buf) + gap = buf; + close(i); + } + top(); + while (!done) { + display(); + i = 0; + ch = getch(); + while (key[i] != '\0' && ch != key[i]) + ++i; + (*func[i])(); + } + endwin(); + return (0); +} diff --git a/1991/ant/index.html b/1991/ant/index.html index 6c71de905..ef24aca8c 100644 --- a/1991/ant/index.html +++ b/1991/ant/index.html @@ -403,8 +403,9 @@ Location: CA - Canada

To build:

    make all
-

There is an alternate version that might feel a bit more -familiar to vi(m) users.

+

There is an alternate version that might feel a bit more familiar to vi(m) +users. Additionally, the author provided deobfuscated versions including one for +C89. See Alternate code below.

To use:

    ./ant some_file

NOTE: the file must already exist and not specifying any arg will make the @@ -415,19 +416,28 @@ program exit without doing anything.

    make mole
     ./ant mole

Alternate code:

-

This version changes the commands slightly so that to go to the first column you -should enter 0, to go to the last column you should enter $, to quit you -should enter q, to go back a word you should enter b and to go forwards a -word you should enter w. Also, and perhaps most useful, rather than having to -hit ctrl-L (form-feed, \f) to get back to command mode you can use the usual -ESC (\x1b).

+

The author provided us with deobfuscated versions including one for C89. The two +C files in deobfuscated, +deobfuscated/ant.c and +deobfuscated/ant-c89.c and the +deobfuscated/Makefile will allow +you to look at them and compile them if you wish. These are exactly like the +original in every way, including in use, except they are deobfuscated.

+

The other version, ant.alt.c changes the +commands slightly so that to go to the first column you should enter 0, to go +to the last column you should enter $, to quit you should enter q, to go +back a word you should enter b and to go forwards a word you should enter w. +Also, and perhaps most useful, rather than having to hit ctrl-L (form-feed, +\f) to get back to command mode you can use the usual ESC (\x1b).

These will make it slightly less unwieldy for those familiar with vi(m); the rest was unchanged.

Alternate build:

    make alt

Alternate use:

-

Use ant.alt as you would ant above with the changes in the input keys. See -the author’s remarks for the remaining keys.

+

For the deobfuscated versions, use ant.alt2 and ant.alt2-c89 as you would +ant above; for the other one, ant.alt, use it as you would ant above but +with the changes in the input keys described above. See the author’s remarks for +the remaining commands.

Judges’ remarks:

The author was kind enough to supply a list of references below, in case you are still confused after read the source! :-)

@@ -540,6 +550,9 @@ ISBN 0-13-822305-X, chapter 5

  • Makefile - entry Makefile
  • ant.alt.c - alternate source code
  • ant.orig.c - original source code
  • +
  • deobfuscated/ant-c89.c - author provided deobfuscated code converted from K&R
  • +
  • deobfuscated/ant.c - author provided deobfuscated code
  • +
  • deobfuscated/Makefile - author provided Makefile for deobfuscated code
  • Secondary files

      diff --git a/1992/ant/.entry.json b/1992/ant/.entry.json index 262f2fa60..83f70a180 100644 --- a/1992/ant/.entry.json +++ b/1992/ant/.entry.json @@ -41,6 +41,22 @@ "display_via_github" : true, "entry_text" : "script to try entry" }, + { + "file_path" : "deobfuscated/ant.c", + "inventory_order" : 140, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided deobfuscated code" + }, + { + "file_path" : "deobfuscated/sleep.c", + "inventory_order" : 140, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided code for those who need a nap" + }, { "file_path" : "ant.README.txt", "inventory_order" : 150, @@ -57,6 +73,30 @@ "display_via_github" : true, "entry_text" : "Makefile to demonstrate entry" }, + { + "file_path" : "deobfuscated/Makefile", + "inventory_order" : 150, + "OK_to_edit" : true, + "display_as" : "makefile", + "display_via_github" : true, + "entry_text" : "author provided Makefile for deobfuscated code" + }, + { + "file_path" : "try.alt.sh", + "inventory_order" : 150, + "OK_to_edit" : true, + "display_as" : "shellscript", + "display_via_github" : true, + "entry_text" : "script to try deobfuscated code" + }, + { + "file_path" : "ant.test.alt.mk", + "inventory_order" : 160, + "OK_to_edit" : true, + "display_as" : "makefile", + "display_via_github" : true, + "entry_text" : "Makefile to demonstrate deobfuscated code" + }, { "file_path" : "1992_ant.tar.bz2", "inventory_order" : 1415926535, diff --git a/1992/ant/.gitignore b/1992/ant/.gitignore index e27538867..74058b461 100644 --- a/1992/ant/.gitignore +++ b/1992/ant/.gitignore @@ -2,8 +2,11 @@ # sort with: ../../bin/sgi.sh *.dSYM am +am.alt am.safe +am.safe.alt ant +ant.alt ant.orig indent indent.c diff --git a/1992/ant/Makefile b/1992/ant/Makefile index ac6d5ef9e..d21e86443 100644 --- a/1992/ant/Makefile +++ b/1992/ant/Makefile @@ -117,8 +117,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= deobfuscated/${PROG}.o +ALT_TARGET= deobfuscated/${PROG} ################# @@ -146,9 +146,33 @@ am: ant # alternative executable # -alt: data ${ALT_TARGET} +alt: data ${PROG}.alt @${TRUE} +# We keep the alternate code, the deobfuscated code, and its Makefile, in the +# deobfuscated directory but copy the compiled binaries to the entry directory, +# to keep both directories clean, separating the two. The reason we copy the +# binary to the entry directory is so one does not have to do: +# +# ./deobfuscated/ant +# +# but instead just: +# +# ./ant.alt +# +# while still using the Makefile provided with the deobfuscated code. +# +${PROG}.alt: deobfuscated/ant.c + ${MAKE} -C deobfuscated ant + ${CP} -v -f deobfuscated/ant ant.alt + +am.alt: ant.alt + rm -f am.alt + ln deobfuscated/ant am.alt + cp am.alt am.safe.alt + cp am.safe.alt am.alt + rm -f am.safe.alt + # data files # data: ${DATA} @@ -156,7 +180,7 @@ data: ${DATA} # both all and alt # -everything: all alt +everything: all alt am am.alt @${TRUE} @@ -216,7 +240,8 @@ clean: clobber: clean ${RM} -f ${TARGET} ${ALT_TARGET} ${RM} -rf *.dSYM - ${RM} -f am am.safe + ${RM} -f am am.safe am.alt am.safe.alt deobfuscated/ant ${PROG}.alt + ${RM} -f node.* leaf.* @-if [ -e sandwich ]; then \ ${RM} -f sandwich; \ echo 'ate sandwich'; \ @@ -229,10 +254,12 @@ am_clean: ${RM} -f indent.c; \ fi - am_clobber: am_clean rm -f am.safe +am_alt_clobber: + rm -f am.safe.alt + install: @echo "Dr. Spock says that is not logical!" @${TRUE} diff --git a/1992/ant/README.md b/1992/ant/README.md index c7fc351a1..8cb86d9b4 100644 --- a/1992/ant/README.md +++ b/1992/ant/README.md @@ -5,6 +5,10 @@ ``` +The author provided us with an unobfuscated version. See [Alternate +code](#alternate-code) below. + + ## To use: ``` @@ -23,6 +27,31 @@ where `Makefile` is a Makefile to use and `rule` is an optional rule to use. ``` +## Alternate code: + +This version, [ant.c in deobfuscated/](%%REPO_URL%%/1992/ant/deobfuscated/ant.c), was provided by the +author in 2024, and is a deobfuscated version. + + +## Alternate build: + +``` + make alt +``` + + +## Alternate use: + +Use `ant.alt` as you would `ant` above. + + +## Try: + +``` + ./try.alt.sh +``` + + ## Judges' remarks: Like much of POSIX, obfuscation has its place. Your task is to diff --git a/1992/ant/ant.test.alt.mk b/1992/ant/ant.test.alt.mk new file mode 100644 index 000000000..7c1462014 --- /dev/null +++ b/1992/ant/ant.test.alt.mk @@ -0,0 +1,196 @@ +# +# Test makefile for AM +# + +# +# Allow for empty macros. +# +EMPTY= + +# +# Allow for white space in macro assignment. +# +TEXT_1=no white space +TEXT_2 =left hand side +TEXT_3= right hand side +TEXT_4 = both sides +TEXT_5 = tabs boths sides + +# +# Test pseudo targets. +# +all : print_macros repeat redefine many flags multiple split errors done + +print_macros : empty t1 t2 t3 t4 t5 t.all + +# +# Targets with no dependencies. +# +empty : + echo EMPTY='$(EMPTY)' + +t1 : + echo TEXT_1='$(TEXT_1)' + +t2 : + echo TEXT_2='$(TEXT_2)' + +t3 : + echo TEXT_3='$(TEXT_3)' + +t4 : + echo TEXT_4='$(TEXT_4)' + +t5 : + echo TEXT_5='$(TEXT_5)' + +t.all : + echo $(TEXT_1) $(TEXT_2) $(TEXT_3) $(TEXT_4) $(TEXT_5) + +# +# Test redefinition of macros. AM allows redefinition and +# evaluates macros immediately. +# +TEXT_1 =text number 1 +TEXT_2 = test macro split \ + across lines \ + three lines +TEXT_3 = test dollar macro '$$' +TEXT_4 = test dollar again "$$(TEXT_1)" +TEXT_5 = embedded macro '$(TEXT_1)' + +redefine : r1 r2 r3 r4 r5 + +r1 : + echo TEXT_1='$(TEXT_1)' + +r2 : + echo TEXT_2='$(TEXT_2)' + +r3 : + echo TEXT_3='$(TEXT_3)' + +r4 : + echo TEXT_4='$(TEXT_4)' + +r5 : + echo TEXT_5='$(TEXT_5)' + +# +# Try to update a prerequisite more than once. Subsequent occurrences +# should be ignored once a prerequisite has been updated. +# +repeat: t1 repeat.a t3 +repeat.a : t2 t1 + + +# +# Target with multi-line recipe. +# +many : leaf.1 leaf.2 + echo Execute receipe with multiple commands. + ls -1 leaf.* + echo Last line of receipe for target 'many'. + +leaf.1 : + touch leaf.1 + +leaf.2 : + touch leaf.2 + + +# +# Test recipe line flags. +# +flags : silence ignore always combination + +# Command not displayed before execution. +silence : + echo You should not see the 'ls' command printed. + @ls leaf.* + +# Ignore errors from command. +ignore : + echo The 'ls' command should fail but not terminate AM. + -ls unknown + +# This flag is ignored by AM since we don't support a silence option (-n). +always : + +echo The '+' flag is accepted and ignored. + +combination: + -@echo The next displayed line should not be 'ls unknown' + @-ls unknown + @+-echo Combined flags test completed. + + +# +# Multiple targets. +# +multiple : node.2 node.5 + +node.1 node.2 node.3 : leaf.1 leaf.2 + touch node.1 node.2 node.3 + +node.4 node.5 : node.2 leaf.3 + touch node.4 node.5 + +leaf.3 : + touch leaf.3 + + +# +# Test split lines. +# +split : node.6 leaf.4 split.cmd + echo Completed split line tests. + +# Target dependencies split across lines. +node.6 : leaf.1 \ + leaf.2 \ + leaf.3 + echo Test dependency list split across lines. + touch node.6 + +# Target list split across lines. +split.tar \ +leaf.4 \ +leaf.5 : + echo Test target list split across lines + touch leaf.4 leaf.5 + +# Command lines split across lines. +split.cmd: + echo Try splitting command \ + lines across more \ + than one line. + + +# +# Test AM error reports and exit statuses. +# +errors: + -./am.alt test.mk error.1 + -./am.alt test.mk error.2 + -./am.alt test.mk error.3 + +# Target that does not exist, has no dependencies, and no commands. +error.1: + +# Target where dependency does not exist. +error.2: unknown + +# Recipe command causes error. +error.3: t1 fail t2 +fail: + ls -l unknown + + +# +# +# +done: + echo AM Test Complete + +clean: + rm leaf.* node.* diff --git a/1992/ant/ant.test.mk b/1992/ant/ant.test.mk index 987b232ac..e5fd1ac8b 100644 --- a/1992/ant/ant.test.mk +++ b/1992/ant/ant.test.mk @@ -77,7 +77,7 @@ r5 : echo TEXT_5='$(TEXT_5)' # -# Try to update a prerequisite more than once. Subsequent occurences +# Try to update a prerequisite more than once. Subsequent occurrences # should be ignored once a prerequisite has been updated. # repeat: t1 repeat.a t3 @@ -85,7 +85,7 @@ repeat.a : t2 t1 # -# Target with multi-line receipe. +# Target with multi-line recipe. # many : leaf.1 leaf.2 echo Execute receipe with multiple commands. @@ -100,7 +100,7 @@ leaf.2 : # -# Test receipe line flags. +# Test recipe line flags. # flags : silence ignore always combination diff --git a/1992/ant/deobfuscated/Makefile b/1992/ant/deobfuscated/Makefile new file mode 100644 index 000000000..9c2e871d4 --- /dev/null +++ b/1992/ant/deobfuscated/Makefile @@ -0,0 +1,22 @@ +# +# Anthony's Editor +# +# IOCCC 1991 +# +# Winner Best Utility +# + +CFLAGS = -Os -Wno-deprecated-non-prototype -Wno-unsequenced + +all: build + +build: ant sleep + +clean: + -rm -f ant + +ant: ant.c + ${CC} ${CFLAGS} ant.c -o $@ + +sleep: sleep.c + ${CC} ${CFLAGS} sleep.c -o $@ diff --git a/1992/ant/deobfuscated/ant.c b/1992/ant/deobfuscated/ant.c new file mode 100644 index 000000000..51b3fdff9 --- /dev/null +++ b/1992/ant/deobfuscated/ant.c @@ -0,0 +1,242 @@ +/* + * am.c Anthony's Make + * + * Public Domain 1992 by Anthony Howe. All rights released. + * + * + * SYNOPSIS + * + * am [target] + * + * + * REFERENCES + * + * [Mil87] Webb Miller, "A Software Tools Sampler", Prentic Hall, 87 + * ISBN 0-13-822305-X, chaper 2 + * + * [POSIX] POSIX.2 draft 11.2 MAKE + */ + +#include +#include +#include +#include +#include +#include + +#ifndef RULES +#define RULES 500 +#endif + +#define next(p, i) (p += i, p += strspn(p, white), i = strcspn(p, white)) + +char *buf, line[BUFSIZ]; +char *tar[RULES], *dep[RULES], *cmd[RULES], white[] = "\n\t "; + +time_t mtime(); +int target(); +void update(); + +/* + * Return the modification time for file. + * If file does not exist then return zero. + */ +time_t +mtime(f) +char *f; +{ + int j, x; + size_t i = 0; + struct stat s; + next(f, i); + x = f[i]; + f[i] = '\0'; + j = stat(f, &s); + f[i] = x; + return (j < 0 ? 0 : s.st_mtime); +} + +/* + * Find first occurence of target f. All subsequent occurences + * are ignored. Return the rule number, zero (0) is the empty + * rule and indicates no target found. + */ +int +target(f) +char *f; +{ + char *q; + size_t i = 0, j, k = 1; + next(f, i); + while ((q = tar[k]) != NULL) { + j = 0; + while (next(q, j) != 0) { + if (i == j && strncmp(f, q, i) == 0) + return (k); + } + ++k; + } + return (0); +} + +/* + * Try to update a file's dependencies, then the file itself. + * If the file does not exist, has no dependencies, and no + * known commands, then exit with an error. + */ +void +update(f) +char *f; +{ + time_t t = mtime(f); + size_t i = 0, j = t == 0, k = target(f); + char *p = dep[k], *q = cmd[k]; + if (next(p, i) == 0 && q != NULL && *q != '\t' && j) { + fprintf(stderr, "am: Don't know how to make '%s'.\n", f); + exit(1); + } + /* Try and update all out-of-date dependencies first. */ + while (0 < i) { + update(p); + if (t < mtime(p)) + j = 1; + next(p, i); + } + if (j && q != NULL && *q == '\t') { + /* Some systems do not record a file's modification times + * with enough precision. This sleep() guarantees that + * each file has a unique modification time. + */ + sleep(1); + while (*q++ == '\t') { + i = j = 1; + while (0 < strspn(q, "-+@")) { + if (*q == '@') + /* Be silent. */ + i = 0; + if (*q++ == '-') + /* Ignore errors. */ + j = 0; + } + if (i) + puts(q); + if (system(q) != 0 && j) { + fprintf(stderr, "am: Error making '%s'\n", f); + exit(1); + } + q += strlen(q) + 1; + } + cmd[k] = NULL; + } +} + +int +main(argc, argv) +int argc; +char **argv; +{ + FILE *f; + struct stat s; + size_t i, j, k; + char *m, *n, *p, *q, *r; + if (argc < 2) { + fprintf(stderr, "usage: am [target]\n"); + return (2); + } + if (stat(*++argv, &s) != 0 || (f = fopen(*argv, "r")) == NULL) + return (3); + /* Allocate room for expanded target rules. */ + q = buf = malloc(2*s.st_size); + if (buf == NULL) + return (4); + /* Facts: + * + * o When a C program starts, all uninitialized data will be + * zero or NULL. + * + * o line[] contains the current makefile line and r points + * into line[]. line <= r < line + BUFSIZ + * + * o p points to the start of text copied from line[]. + * q points to the next free storage location. + * buf <= p <= q <= buf + s.st_size; + * + * o m points to start of a temporarily stored macro definition. + * + * o i is the number of rules stored. 0 < i < RULES + * + * o When a C program terminates, all open files are closed and + * any allocated memory is freed. + */ + i = 1; + k = 0; + m = NULL; + /* The empty rule. */ + *tar = *dep = *cmd = ""; + while ((r = fgets(line, BUFSIZ, f)) != NULL) { + if (RULES <= i) { + fprintf(stderr, + "am: Number of target-rules exceeds %d.\n", + RULES + ); + return (1); + } + if (k) { + *q++ = ' '; + r += strspn(r, white); + } else { + /* If a target list was saved and we've terminated + * the dependency list, then line[] may be the first + * command in the target recipe. + */ + if (tar[i] != NULL) + cmd[i++] = q; + if (m != NULL && putenv(m)) + fprintf(stderr, + "am: No more environment space.\n"); + m = NULL; + /* Skip comment or blank lines. */ + if (*line == '#' || *line == '\n') + continue; + p = q; + } + while (!(k = *r == '\\' && r[1] == '\n') && *r != '\0') { + if (*r == '$') { + if (r[1] == '(') { + n = r+2; + r += strcspn(r, ")"); + *r++ = '\0'; + n = getenv(n); + if (n != NULL) + q = strcpy(q, n) + strlen(n); + continue; + } + if (*r == r[1]) + ++r; + } + if (*r == '=' && *line != '\t' && m == NULL) { + *q = '\0'; + m = p; + j = 0; + q = next(m, j) + m; + *q++ = *r; + j = 1; + if (next(r, j) == 0) + *q++ = '\0'; + continue; + } + if (*r == ':') { + tar[i] = p; + *r = '\0'; + dep[i] = q+1; + } + if (*r == '\n') + *r = '\0'; + *q++ = *r++; + } + } + fclose(f); + update(2 < argc ? *++argv : tar[1]); + return (0); +} + diff --git a/1992/ant/deobfuscated/sleep.c b/1992/ant/deobfuscated/sleep.c new file mode 100644 index 000000000..a9975b51e --- /dev/null +++ b/1992/ant/deobfuscated/sleep.c @@ -0,0 +1,18 @@ +/* + * sleep.c + */ + +#include + +void +sleep(secs) +unsigned secs; +{ + clock_t start, now; + + start = clock(); + do + now = clock(); + while ((now - start) / CLK_TCK < secs); +} + diff --git a/1992/ant/index.html b/1992/ant/index.html index 3668aa521..8eeea8b0e 100644 --- a/1992/ant/index.html +++ b/1992/ant/index.html @@ -403,6 +403,8 @@ Location: CA - Canada

      To build:

          make all
      +

      The author provided us with an unobfuscated version. See Alternate +code below.

      To use:

          ./ant Makefile
       
      @@ -410,6 +412,15 @@ Location: CA - Canada
       

      where Makefile is a Makefile to use and rule is an optional rule to use.

      Try:

          ./try.sh
      +

      Alternate code:

      +

      This version, ant.c in deobfuscated/, was provided by the +author in 2024, and is a deobfuscated version.

      +

      Alternate build:

      +
          make alt
      +

      Alternate use:

      +

      Use ant.alt as you would ant above.

      +

      Try:

      +
          ./try.alt.sh

      Judges’ remarks:

      Like much of POSIX, obfuscation has its place. Your task is to figure out where.

      @@ -447,8 +458,13 @@ P1003 subcommittee.

    • Makefile - entry Makefile
    • ant.orig.c - original source code
    • try.sh - script to try entry
    • +
    • deobfuscated/ant.c - author provided deobfuscated code
    • +
    • deobfuscated/sleep.c - author provided code for those who need a nap
    • ant.README.txt - am man page
    • ant.test.mk - Makefile to demonstrate entry
    • +
    • deobfuscated/Makefile - author provided Makefile for deobfuscated code
    • +
    • try.alt.sh - script to try deobfuscated code
    • +
    • ant.test.alt.mk - Makefile to demonstrate deobfuscated code

    Secondary files

      diff --git a/1992/ant/try.alt.sh b/1992/ant/try.alt.sh new file mode 100755 index 000000000..36532ec63 --- /dev/null +++ b/1992/ant/try.alt.sh @@ -0,0 +1,35 @@ +#!/usr/bin/env bash +# +# try.sh - demonstrate IOCCC entry 1992/ant alt code +# + +# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it +# this way allows us to have the user specify a different compiler in an easy +# way. +if [[ -z "$CC" ]]; then + CC="cc" +fi + +make CC="$CC" alt >/dev/null || exit 1 + +# clear screen after compilation so that only the entry is shown +clear + +echo "$ ./ant.alt Makefile am.alt # build the tool itself" 1>&2 +read -r -n 1 -p "Press any key to run: ./ant Makefile am: " +echo 1>&2 +./ant.alt Makefile am.alt +echo 1>&2 + + + +echo "$ ./am.alt Makefile am_clobber # clobber everything except am" 1>&2 +read -r -n 1 -p "Press any key to continue: " +echo 1>&2 +./am.alt Makefile am_clobber # clobber everything except am +echo 1>&2 + +echo "$ ./am.alt ant.test.alt.mk # run the test Makefile with am" 1>&2 +read -r -n 1 -p "Press any key to continue: " +echo 1>&2 +./am.alt ant.test.alt.mk # run the test Makefile with am.alt diff --git a/1993/ant/.entry.json b/1993/ant/.entry.json index 41a4cc3ad..c6e2e720b 100644 --- a/1993/ant/.entry.json +++ b/1993/ant/.entry.json @@ -49,6 +49,46 @@ "display_via_github" : true, "entry_text" : "script to try entry" }, + { + "file_path" : "deobfuscated/ant-c89.c", + "inventory_order" : 120, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided deobfuscated code converted from K&R" + }, + { + "file_path" : "deobfuscated/ant.c", + "inventory_order" : 120, + "OK_to_edit" : true, + "display_as" : "c", + "display_via_github" : true, + "entry_text" : "author provided deobfuscated code" + }, + { + "file_path" : "try.alt.sh", + "inventory_order" : 130, + "OK_to_edit" : true, + "display_as" : "shellscript", + "display_via_github" : true, + "entry_text" : "script to try deobfuscated code" + }, + { + "file_path" : "deobfuscated/Makefile", + "inventory_order" : 140, + "OK_to_edit" : true, + "display_as" : "makefile", + "display_via_github" : true, + "entry_text" : "author provided Makefile for deobfuscated code" + }, + { + "file_path" : "deobfuscated/test.mk", + "inventory_order" : 140, + "OK_to_edit" : true, + "display_as" : "makefile", + "display_via_github" : true, + "entry_text" : "author provided test suite Makefile for deobfuscated code" + }, { "file_path" : "ant.test.mk", "inventory_order" : 150, @@ -60,11 +100,19 @@ { "file_path" : "ants.txt", "inventory_order" : 150, - "OK_to_edit" : true, + "OK_to_edit" : false, "display_as" : "text", "display_via_github" : false, "entry_text" : "lyrics of the Ants Go Marching song" }, + { + "file_path" : "ant.alt.test.mk", + "inventory_order" : 160, + "OK_to_edit" : true, + "display_as" : "makefile", + "display_via_github" : true, + "entry_text" : "test suite Makefile for deobfuscated code" + }, { "file_path" : "1993_ant.tar.bz2", "inventory_order" : 1415926535, diff --git a/1993/ant/.gitignore b/1993/ant/.gitignore index 541916dc9..264c6ecdf 100644 --- a/1993/ant/.gitignore +++ b/1993/ant/.gitignore @@ -2,8 +2,10 @@ # sort with: ../../bin/sgi.sh *.dSYM ag +ag.alt ag.txt ant +ant.alt ant.orig indent indent.c diff --git a/1993/ant/Makefile b/1993/ant/Makefile index 758e07fed..c7023057b 100644 --- a/1993/ant/Makefile +++ b/1993/ant/Makefile @@ -116,8 +116,8 @@ OBJ= ${PROG}.o DATA= TARGET= ${PROG} # -ALT_OBJ= -ALT_TARGET= +ALT_OBJ= deobfuscated/${PROG}.o +ALT_TARGET= deobfuscated/${PROG} ################# @@ -145,9 +145,30 @@ ag.txt: ${PROG}.txt # alternative executable # -alt: data ${ALT_TARGET} +alt: data ${PROG}.alt @${TRUE} +# We keep the alternate code, the deobfuscated code, and its Makefile, in the +# deobfuscated directory but copy the compiled binaries to the entry directory, +# to keep both directories clean, separating the two. The reason we copy the +# binary to the entry directory is so one does not have to do: +# +# ./deobfuscated/ant +# +# but instead just: +# +# ./ant.alt +# +# while still using the Makefile provided with the deobfuscated code. +# +${PROG}.alt: deobfuscated/ant.c + ${MAKE} -C deobfuscated ant + ${CP} -v -f deobfuscated/ant ant.alt + +ag.alt: ${PROG}.alt + ${RM} -f $@ + ${CP} -f $< $@ + # data files # data: ${DATA} @@ -155,7 +176,7 @@ data: ${DATA} # both all and alt # -everything: all alt +everything: all alt ag ag.alt @${TRUE} @@ -215,7 +236,7 @@ clean: clobber: clean ${RM} -f ${TARGET} ${ALT_TARGET} ${RM} -rf *.dSYM - ${RM} -f ag ag.txt + ${RM} -f ag ag.txt ant.alt ag.alt deobfuscated/ant deobfuscated/ant-c89 deobfuscated/ag deobfuscated/ag-c89 @-if [ -e sandwich ]; then \ ${RM} -f sandwich; \ echo 'ate sandwich'; \ diff --git a/1993/ant/README.md b/1993/ant/README.md index 4830f34cc..23e0c3a4d 100644 --- a/1993/ant/README.md +++ b/1993/ant/README.md @@ -4,6 +4,9 @@ make all ``` +The author provided a deobfuscated version. See [Alternate +code](#alternate-code) below. + ### Bugs and (Mis)features: @@ -31,6 +34,35 @@ For more detailed information see [1993/ant in bugs.html](../../bugs.html#1993_a ``` +## Alternate code: + +The [ant.c in deobfuscated/](%%REPO_URL%%/1993/ant/deobfuscated/ant.c) is a +deobfuscated version provided by the author. You can look at this code if you +want some clues in how it works. + + +## Alternate build: + +If you wish to build this deobfuscated version, you can do so like: + + +``` + make alt +``` + + +## Alternate use: + +Use `ant.alt` like you would `ant` above. + + +## Alternate try: + +``` + ./try.alt.sh +``` + + ## Judges' remarks: See the author's POSIX P1003.2-like documentation file [ant.txt](ant.txt) for diff --git a/1993/ant/ant.alt.test.mk b/1993/ant/ant.alt.test.mk new file mode 100644 index 000000000..6dbf7de57 --- /dev/null +++ b/1993/ant/ant.alt.test.mk @@ -0,0 +1,240 @@ +# +# Test Driver for Anthony's Grep +# +# Public Domain 1992, 1993 by Anthony Howe. No warrant.alty. +# + +SHELL=/bin/sh +PRG=./ant.alt + +all: ant.alt char word anchor literal wild closure option branch sub class + +# +# Built the entry +# +ant.alt: Makefile + make -f Makefile ant.alt + +# +# Test simple text patterns without the use of meta characters. +# + +empty: + $(PRG) '' ant.alt.test.mk + +char: + $(PRG) 'q' ant.alt.test.mk + +word: + $(PRG) 'simple' ant.alt.test.mk + +# +# Test meta characters. +# + +anchor: anchor1 anchor2 anchor3 anchor4 anchor5 + +anchor1: + $(PRG) '^anchor1' ant.alt.test.mk + +anchor2: + $(PRG) 'Grep$$' ant.alt.test.mk + +# +# Find all empty lines. +# +anchor3: + $(PRG) '^$$' ant.alt.test.mk + +# +# This is valid but will never match. +# +anchor4: + -$(PRG) 'x^a' ant.alt.test.mk + +# +# This is valid but will never match. +# +anchor5: + -$(PRG) 'mk$$x' ant.alt.test.mk + +literal: literal1 literal2 + +# +# Every line with a dollar-sign. +# +literal1: + $(PRG) '\$$' ant.alt.test.mk + +# +# Every line with a backslash. +# +literal2: + $(PRG) '\\' ant.alt.test.mk + +# +# wild #1# +# wild #a# +# wild #%# +# +wild: + $(PRG) '#.#' ant.alt.test.mk + +# +# closure !! +# closure !x! +# closure !xxxxxx! +# +closure: + $(PRG) 'closure !x*!' ant.alt.test.mk + +# +# option ++ +# option +a+ +# option +b+ +# option +c+ +# option +abc+ +# +option: option1 option2 + +option1: + $(PRG) '+b?+' ant.alt.test.mk + +option2: + $(PRG) '+.?+' ant.alt.test.mk + +branch: branch1 branch2 branch3 branch4 branch5 branch6 + +branch1: + $(PRG) 'q|simple' ant.alt.test.mk + +# +# This pattern should be the same as '(^all)|(Public)|(Grep$)'. +# +branch2: + $(PRG) '^all|Public|Grep$$' ant.alt.test.mk + +# +# This pattern should generate the same results as branch2. +# +branch3: + $(PRG) 'Grep$$|^all|Public' ant.alt.test.mk + +# +# Null expression between start of pattern and vertical-line. +# +branch4: + $(PRG) '|Grep' ant.alt.test.mk + +# +# Null expression between vertical-line and end of pattern. +# +branch5: + $(PRG) 'Grep|' ant.alt.test.mk + +# +# Null expression between vertical-line and vertical-line. +# +branch6: + $(PRG) 'all||Grep' ant.alt.test.mk + +# +# sub aabcbcbcxx +# sub aagxx +# sub aaggxx +# sub aadddxx +# sub aaxx +# +sub: sub0 sub1 sub2 sub3 sub4 sub5 lparen1 lparen2 rparen1 rparen2 + +# +# Null sub-expressions. +# +sub0: + $(PRG) 's()u()b()' ant.alt.test.mk + +sub1: + $(PRG) '#(1|%)#' ant.alt.test.mk + +sub2: + $(PRG) 'aa((bc)*|g)xx' ant.alt.test.mk + +# +# Null expression between the left-parenthesis and the vertical-line. +# +sub3: + $(PRG) '#(|1)#' ant.alt.test.mk + +# +# Null expression between the vertical-line and the right-parenthesis. +# +sub4: + $(PRG) '#(1|)#' ant.alt.test.mk + +# +# Null expression between the vertical-line and the right-parenthesis. +# +sub5: + $(PRG) '#(%||1)#' ant.alt.test.mk + +# +# Missing left-parenthesis generates an error. +# +lparen1: + -$(PRG) 'left ( only' ant.alt.test.mk + +lparen2: + $(PRG) 'left \( only' ant.alt.test.mk + +# +# Right-parenthesis without preceding left parenthesis should be a literal. +# +rparen1: + -$(PRG) 'right ) only' ant.alt.test.mk + +rparen2: + $(PRG) 'right \) only' ant.alt.test.mk + +# +# 12345678 +# ----------------- +# =0= 1 45 +# =1= 2 45 78 +# =2= 2 45 +# =3= 2 45 78 +# =4= 2 45 +# =5= 2 45 +# =6= 2 45 +# =7= 2 45 +# =8= 2 45 +# =9= 1 45 +# =]= 23 6 +# =-= 2 4 678 +# = = 2 4 6 +# +class: class1 class2 class3 class4 class5 class6 class7 class8 + +class1: + $(PRG) '=[09]=' ant.alt.test.mk + +class2: + $(PRG) '=[^09]=' ant.alt.test.mk + +class3: + $(PRG) '=[]]=' ant.alt.test.mk + +class4: + $(PRG) '=[^]]=' ant.alt.test.mk + +class5: + $(PRG) '=[0-9]=' ant.alt.test.mk + +class6: + $(PRG) '=[^0-9]=' ant.alt.test.mk + +class7: + -$(PRG) '=[3-1]=' ant.alt.test.mk + +class8: + $(PRG) '=[-13]=' ant.alt.test.mk + diff --git a/1993/ant/deobfuscated/Makefile b/1993/ant/deobfuscated/Makefile new file mode 100644 index 000000000..825354fc9 --- /dev/null +++ b/1993/ant/deobfuscated/Makefile @@ -0,0 +1,27 @@ +CFLAGS= -Os -Wno-deprecated-non-prototype + +all: build + +build: ant ant-c89 + +clean: + -rm -f ant ant-c89 *.out + +# Original K&R version. +ant$E: ant.c + ${CC} ${CFLAGS} ant.c -o $@ + +ant-c89$E: ant-c89.c + ${CC} ${CFLAGS} ant-c89.c -o $@ + +test: ant$E + ${MAKE} -f test.mk PRG=./ant >ant.out 2>&1 + +test-c89: ant-c89$E + ${MAKE} -f test.mk PRG=./ant-c89 >ant-c89.out 2>&1 + +# Make sure the old and revised versions behave the same. +test-compare: build test test-c89 + sed -e 's/-c89//' ant-c89.out | diff -u ant.out - + rm *.out + diff --git a/1993/ant/deobfuscated/ant-c89.c b/1993/ant/deobfuscated/ant-c89.c new file mode 100644 index 000000000..520692b9c --- /dev/null +++ b/1993/ant/deobfuscated/ant-c89.c @@ -0,0 +1,425 @@ +/* + * ag.c + * + * Anthony's Grep + * + * Public Domain 1992, 2021 by Anthony Howe. All rights released. + * + * Synopsis: ag [files...] + */ + +#include +#include + +#ifndef ARRAY +#define ARRAY 512 +#endif + +#define EXIT_MATCH 0 +#define EXIT_NOMATCH 1 +#define EXIT_USAGE 2 +#define EXIT_ERROR 3 + +/* + * Non-deterministic Finite-state Automaton + * + * An NFA is a directed graph whose nodes are called states. Each + * state is either a labeled state denoting a literal value, or a + * NIL state that has no label. Each state has at most two edges + * leaving it. There is only one start state and one final state, + * which may be the same state. + * + * Various state-structures can be represented by an array. These + * structures have only one start point being the left most index, + * and one end point being the right most index. + * + * a ...[a]... + * + * ab ...[a][b]... + * + * ^a [bol][a]... + * + * a$ ...[a][eol] + * + * a.b ...[a][wild][b]... + * _ + * v \ + * a* ...[\][a][\]... + * \____^ + * + * a? ...[\][a]... + * \___^ + * _______________ + * / v + * a|b ...[\][a][/][stop][pass][b]... + * \_____________^ + * + * [a0-9] ...[class][a][0][1][2][3][4][5][6][7][8][9][stop]... + * + * [^a0-9] ...[nclass][a][0][1][2][3][4][5][6][7][8][9][stop]... + * + * _____________ _______________ + * / v/ v + * a|b|c ...[\][a][/][stop][\][b][/][stop][pass][c]... + * \_____________^\_____________^ + * + * _ _______________ + * v \ / v + * a*(b|c) ...[\][a][\][\][b][/][stop][pass][c]... + * \____^ \_____________^ + */ + +#define BOL ('\n') +#define EOL ('\n') +#define STOP ('\n') +#define WILD (0) +#define CLASS (-1) +#define NCLASS (-2) +#define PASS (-3) +#define JUMP(n) (-4-(n)) +#define CHAR(c) (c) +#define ISJUMP(x) ((x) <= PASS) +#define ISCHAR(x) (0 <= (x)) + +/* + * Special member that is contained in all sets. It is the location + * of the WILD element that the pattern array is initialised with in + * main(). Due to the way from() performs the pattern search, this + * member is always the first member of a set and so can be used to + * delimit sets. + */ +#define MEMBER 2 + +static int chr; +static int final; +static int nesting; +static int array[ARRAY], next; + +/* + * The number of states will always be related to the number of + * unique sets in set[], which is less-than-equal-to next_set. + * There is no need to bounds check dfa[][] since next_set + * is bounds checked in from() and would cause an error well in + * advance of overflowing the total number of possible states. + */ +static int dfa[ARRAY][ARRAY]; +static int set[ARRAY], new_set, next_set; + +void expr(char **); + +/* + * Allocate an element from the pool of free elements. The + * global variable 'next' points to the next free element in + * the pool. Return the allocated element's index. + */ +int +new(int c) +{ + if (ARRAY <= next) { + fprintf(stderr, "ag: Pattern too long.\n"); + exit(EXIT_ERROR); + } + array[next] = c; + return (next++); +} + +/* + * literal + * . + * class + * character + * \ character + * + * class + * [ ] ] + * [ range ] + * [ ] range ] + * [ ^ range ] + * [ ^ ] range ] + * + * range + * - + * character + * range character + * character_low - character_hi + * range character_low - character_hi + */ +void +literal(char **p) +{ + int i, j; + if (**p == '.') { + new(WILD); + } else if (**p == '[') { + ++*p; + i = new(CLASS); + if (**p == '^') { + ++*p; + array[i] = NCLASS; + } + if (**p == ']') { + ++*p; + new(CHAR(']')); + } + while ((i = **p) != ']') { + if ((*p)[1] == '-' && i < (j = (*p)[2])) { + while (i <= j) + new(CHAR(i++)); + *p += 3; + } else { + new(CHAR(i)); + ++*p; + } + } + new(STOP); + } else { + if (**p == '\\') + ++*p; + new(CHAR(**p)); + } + ++*p; +} + +/* + * factor + * ^ + * $ + * literal + * ( expr ) + * factor * + */ +void +factor(char **p) +{ + int i = new(PASS); + if (**p == '^') { + ++*p; + new(BOL); + } else if (**p == '$') { + ++*p; + new(EOL); + } else if (**p == '(') { + ++*p; + ++nesting; + expr(p); + if (**p != ')') { + fprintf(stderr, "ag: Missing ')'.\n"); + exit(EXIT_ERROR); + } + --nesting; + ++*p; + } else { + literal(p); + } + if (**p == '*') { + ++*p; + array[i] = JUMP(next); + new(JUMP(i+1)); + } else if (**p == '?') { + ++*p; + array[i] = JUMP(next); + } +} + +/* + * term + * factor + * term factor + */ +void +term(char **p) +{ + while (**p != '|' && (0 == nesting || **p != ')') && **p != '\0') + factor(p); +} + +/* + * expr + * term + * expr | term + */ +void +expr(char **p) +{ + int i, j; + i = new(PASS); + term(p); + while (**p == '|') { + ++*p; + j = new(PASS); + new(STOP); + array[i] = JUMP(next); + i = new(PASS); + term(p); + array[j] = JUMP(next); + } +} + +/* + * If element pointed to by 'p' is CLASS, return true if 'c' is in + * the class. If the element is NCLASS, return true if 'c' is not + * in the class. Pass back the end of the character class in 'p'. + */ +int +inclass(int *p) +{ + int i = 0, j = 0; + if (array[*p] == CLASS || (j = array[*p] == NCLASS)) { + while (array[++*p] != STOP) + if (array[*p] == CHAR(chr)) + i = 1; + } + return (i ^ j); +} + +/* + * Return true if the end point (final state) can be reached + * from element 'p' without crossing any labeled elements. + */ +int +isfinal(int p) +{ + return ( + final || p == next || ( + ISJUMP(array[p]) && ( + (array[p] != PASS && isfinal(JUMP(array[p]))) + || isfinal(p+1) + ) + ) + ); +} + +/* + * Find all labeled elements reachable from element 'p' and add to + * the global set 'new_set' those that are labeled with global 'chr'. + * 'final' is true if the final state can be reached. + */ +void +from(int p) +{ + int i = new_set; + if (next <= p) + return; + if (ISJUMP(array[p])) { + if (array[p] != PASS) + from(JUMP(array[p])); + from(p+1); + } else if (WILD == array[p] || array[p] == CHAR(chr) || inclass(&p)) { + /* If element 'p' already a member of set 't' then return. */ + while (i < next_set) + if (set[i++] == p) + return; + /* Can we reach the final state from here? */ + final = isfinal(p+1); + + if (ARRAY <= next_set) { + fprintf(stderr, "ag: Out of space.\n"); + exit(EXIT_ERROR); + } + /* Add element 'p' to set 't'. */ + set[next_set++] = p; + } +} + +/* + * Return true if the given string matches. The search string must + * be of the form "\ntext\n\0" in order to handle line anchoring. + */ +int +match(char *p) +{ + int state, i, j, k; + final = state = 0; + while (*p != '\0' && 0 <= state) { + if (0 < (i = dfa[state][*p])) { + /* Transition on known DFA state. */ + state = i; + } else { + /* Perform lazy DFA evaluation from NFA. + * + * Compute new_set, which represents a transition + * from the current state's set on character *p. + * dfa[state]['\0'] contains the set[] index for + * the current state. + */ + chr = *p; + i = dfa[state]['\0']; + j = new_set = next_set; + do + from(set[i++]+1); + while (set[i] != MEMBER); + + /* Determine if this is a known set or not. */ + i = k = 0; + while (i < new_set) { + if (set[i] == MEMBER) { + j = new_set; + ++k; + } + if (set[i++] == set[j]) { + if (next_set <= ++j) { + j = new_set; + if (set[i] == MEMBER) { + /* Known set found. */ + next_set = new_set; + break; + } + } + } else { + j = new_set; + } + } + if (new_set < next_set) + /* New set found. */ + dfa[++k]['\0'] = new_set; + state = dfa[state][*p] = final ? -1 : k; + } + ++p; + } + return (state < 0); +} + +int +main(int argc, char **argv) +{ + int error; + FILE *file; + char *name, line[BUFSIZ+1]; + + if (--argc < 1) { + fprintf(stderr, "usage: ag [files...]\n"); + return (EXIT_USAGE); + } + + /* Initialise array[] = [pass][3][wild][1]... */ + new(PASS); + new(JUMP(next+2)); + new(WILD); + new(JUMP(next-1)); + + expr(&(*++argv)); + + *line = BOL; + next_set = 1; + error = EXIT_NOMATCH; + do { + name = "-"; + file = stdin; + if (1 < argc && **++argv != '-') { + if (NULL == (file = fopen(name = *argv, "r"))) { + fprintf(stderr, + "ag: Failed to open '%s'.\n", name); + error = EXIT_ERROR; + continue; + } + } + while (fgets(line+1, BUFSIZ, file) != NULL) { + if (match(line)) { + printf("%s:%s", name, line+1); + error = EXIT_MATCH; + } + } + fclose(file); + } while (1 < --argc); + return (error); +} diff --git a/1993/ant/deobfuscated/ant.c b/1993/ant/deobfuscated/ant.c new file mode 100644 index 000000000..b42dac68f --- /dev/null +++ b/1993/ant/deobfuscated/ant.c @@ -0,0 +1,449 @@ +/* + * ag.c + * + * Anthony's Grep + * + * Public Domain 1992, 1993 by Anthony Howe. All rights released. + * + * Synopsis: ag [files...] + */ + +#include +#include + +#ifndef ARRAY +#define ARRAY 512 +#endif + +#define EXIT_MATCH 0 +#define EXIT_NOMATCH 1 +#define EXIT_USAGE 2 +#define EXIT_ERROR 3 + +/* + * Non-deterministic Finite-state Automaton + * + * An NFA is a directed graph whose nodes are called states. Each + * state is either a labeled state denoting a literal value, or a + * NIL state that has no label. Each state has at most two edges + * leaving it. There is only one start state and one final state, + * which may be the same state. + * + * Various state-structures can be represented by an array. These + * structures have only one start point being the left most index, + * and one end point being the right most index. + * + * a ...[a]... + * + * ab ...[a][b]... + * + * ^a [bol][a]... + * + * a$ ...[a][eol] + * + * a.b ...[a][wild][b]... + * _ + * v \ + * a* ...[\][a][\]... + * \____^ + * + * a? ...[\][a]... + * \___^ + * _______________ + * / v + * a|b ...[\][a][/][stop][pass][b]... + * \_____________^ + * + * [a0-9] ...[class][a][0][1][2][3][4][5][6][7][8][9][stop]... + * + * [^a0-9] ...[nclass][a][0][1][2][3][4][5][6][7][8][9][stop]... + * + * _____________ _______________ + * / v/ v + * a|b|c ...[\][a][/][stop][\][b][/][stop][pass][c]... + * \_____________^\_____________^ + * + * _ _______________ + * v \ / v + * a*(b|c) ...[\][a][\][\][b][/][stop][pass][c]... + * \____^ \_____________^ + */ + +#define BOL ('\n') +#define EOL ('\n') +#define STOP ('\n') +#define WILD (0) +#define CLASS (-1) +#define NCLASS (-2) +#define PASS (-3) +#define JUMP(n) (-4-(n)) +#define CHAR(c) (c) +#define ISJUMP(x) ((x) <= PASS) +#define ISCHAR(x) (0 <= (x)) + +/* + * Special member that is contained in all sets. It is the location + * of the WILD element that the pattern array is initialised with in + * main(). Due to the way from() performs the pattern search, this + * member is always the first member of a set and so can be used to + * delimit sets. + */ +#define MEMBER 2 + +typedef int I; +typedef char C; +typedef void V; + +I chr; +I final; +I nesting; +I array[ARRAY], next; + +/* + * The number of states will always be related to the number of + * unique sets in set[], which is less-than-equal-to next_set. + * There is no need to bounds check dfa[][] since next_set + * is bounds checked in from() and would cause an error well in + * advance of overflowing the total number of possible states. + */ +I dfa[ARRAY][ARRAY]; +I set[ARRAY], new_set, next_set; + +I new(); +I match(); +I inclass(); +I isfinal(); +V expr(); +V term(); +V factor(); +V literal(); +V from(); + +I +main(argc, argv) +I argc; +C **argv; +{ + I error; + FILE *file; + C *name, line[BUFSIZ+1]; + + if (--argc < 1) { + fprintf(stderr, "usage: ag [files...]\n"); + return (EXIT_USAGE); + } + + /* Initialise array[] = [pass][3][wild][1]... */ + new(PASS); + new(JUMP(next+2)); + new(WILD); + new(JUMP(next-1)); + + expr(&(*++argv)); + + *line = BOL; + next_set = 1; + error = EXIT_NOMATCH; + do { + name = "-"; + file = stdin; + if (1 < argc && **++argv != '-') { + if (NULL == (file = fopen(name = *argv, "r"))) { + fprintf(stderr, + "ag: Failed to open '%s'.\n", name); + error = EXIT_ERROR; + continue; + } + } + while (fgets(line+1, BUFSIZ, file) != NULL) { + if (match(line)) { + printf("%s:%s", name, line+1); + error = EXIT_MATCH; + } + } + fclose(file); + } while (1 < --argc); + return (error); +} + +/* + * expr + * term + * expr | term + */ +V +expr(p) +C **p; +{ + I i, j; + i = new(PASS); + term(p); + while (**p == '|') { + ++*p; + j = new(PASS); + new(STOP); + array[i] = JUMP(next); + i = new(PASS); + term(p); + array[j] = JUMP(next); + } +} + +/* + * term + * factor + * term factor + */ +V +term(p) +C **p; +{ + while (**p != '|' && (0 == nesting || **p != ')') && **p != '\0') + factor(p); +} + +/* + * factor + * ^ + * $ + * literal + * ( expr ) + * factor * + */ +V +factor(p) +C **p; +{ + I i = new(PASS); + if (**p == '^') { + ++*p; + new(BOL); + } else if (**p == '$') { + ++*p; + new(EOL); + } else if (**p == '(') { + ++*p; + ++nesting; + expr(p); + if (**p != ')') { + fprintf(stderr, "ag: Missing ')'.\n"); + exit(EXIT_ERROR); + } + --nesting; + ++*p; + } else { + literal(p); + } + if (**p == '*') { + ++*p; + array[i] = JUMP(next); + new(JUMP(i+1)); + } else if (**p == '?') { + ++*p; + array[i] = JUMP(next); + } +} + +/* + * literal + * . + * class + * character + * \ character + * + * class + * [ ] ] + * [ range ] + * [ ] range ] + * [ ^ range ] + * [ ^ ] range ] + * + * range + * - + * character + * range character + * character_low - character_hi + * range character_low - character_hi + */ +V +literal(p) +C **p; +{ + I i, j; + if (**p == '.') { + new(WILD); + } else if (**p == '[') { + ++*p; + i = new(CLASS); + if (**p == '^') { + ++*p; + array[i] = NCLASS; + } + if (**p == ']') { + ++*p; + new(CHAR(']')); + } + while ((i = **p) != ']') { + if ((*p)[1] == '-' && i < (j = (*p)[2])) { + while (i <= j) + new(CHAR(i++)); + *p += 3; + } else { + new(CHAR(i)); + ++*p; + } + } + new(STOP); + } else { + if (**p == '\\') + ++*p; + new(CHAR(**p)); + } + ++*p; +} + +/* + * Allocate an element from the pool of free elements. The + * global variable 'next' points to the next free element in + * the pool. Return the allocated element's index. + */ +I +new(c) +I c; +{ + if (ARRAY <= next) { + fprintf(stderr, "ag: Pattern too long.\n"); + exit(EXIT_ERROR); + } + array[next] = c; + return (next++); +} + +/* + * Find all labeled elements reachable from element 'p' and add to + * the global set 'new_set' those that are labeled with global 'chr'. + * 'final' is true if the final state can be reached. + */ +V +from(p) +I p; +{ + I i = new_set; + if (next <= p) + return; + if (ISJUMP(array[p])) { + if (array[p] != PASS) + from(JUMP(array[p])); + from(p+1); + } else if (WILD == array[p] || array[p] == CHAR(chr) || inclass(&p)) { + /* If element 'p' already a member of set 't' then return. */ + while (i < next_set) + if (set[i++] == p) + return; + /* Can we reach the final state from here? */ + final = isfinal(p+1); + + if (ARRAY <= next_set) { + fprintf(stderr, "ag: Out of space.\n"); + exit(EXIT_ERROR); + } + /* Add element 'p' to set 't'. */ + set[next_set++] = p; + } +} + +/* + * If element pointed to by 'p' is CLASS, return true if 'c' is in + * the class. If the element is NCLASS, return true if 'c' is not + * in the class. Pass back the end of the character class in 'p'. + */ +I +inclass(p) +I *p; +{ + I i = 0, j = 0; + if (array[*p] == CLASS || (j = array[*p] == NCLASS)) { + while (array[++*p] != STOP) + if (array[*p] == CHAR(chr)) + i = 1; + } + return (i ^ j); +} + +/* + * Return true if the end point (final state) can be reached + * from element 'p' without crossing any labeled elements. + */ +I +isfinal(p) +I p; +{ + return ( + final || p == next || ( + ISJUMP(array[p]) && ( + (array[p] != PASS && isfinal(JUMP(array[p]))) + || isfinal(p+1) + ) + ) + ); +} + +/* + * Return true if the given string matches. The search string must + * be of the form "\ntext\n\0" in order to handle line anchoring. + */ +I +match(p) +C *p; +{ + I state, i, j, k; + final = state = 0; + while (*p != '\0' && 0 <= state) { + if (0 < (i = dfa[state][*p])) { + /* Transition on known DFA state. */ + state = i; + } else { + /* Perform lazy DFA evaluation from NFA. + * + * Compute new_set, which represents a transition + * from the current state's set on character *p. + * dfa[state]['\0'] contains the set[] index for + * the current state. + */ + chr = *p; + i = dfa[state]['\0']; + j = new_set = next_set; + do + from(set[i++]+1); + while (set[i] != MEMBER); + + /* Determine if this is a known set or not. */ + i = k = 0; + while (i < new_set) { + if (set[i] == MEMBER) { + j = new_set; + ++k; + } + if (set[i++] == set[j]) { + if (next_set <= ++j) { + j = new_set; + if (set[i] == MEMBER) { + /* Known set found. */ + next_set = new_set; + break; + } + } + } else { + j = new_set; + } + } + if (new_set < next_set) + /* New set found. */ + dfa[++k]['\0'] = new_set; + state = dfa[state][*p] = final ? -1 : k; + } + ++p; + } + return (state < 0); +} + diff --git a/1993/ant/deobfuscated/test.mk b/1993/ant/deobfuscated/test.mk new file mode 100644 index 000000000..041459bc9 --- /dev/null +++ b/1993/ant/deobfuscated/test.mk @@ -0,0 +1,233 @@ +# +# Test Driver for Anthony's Grep +# +# Public Domain 1992, 1993 by Anthony Howe. No warranty. +# + +SHELL = /bin/sh + +all: char word anchor literal wild closure option branch sub class + +# +# Test simple text patterns without the use of meta characters. +# + +empty: + $(PRG) '' test.mk + +char: + $(PRG) 'q' test.mk + +word: + $(PRG) 'simple' test.mk + +# +# Test meta characters. +# + +anchor: anchor1 anchor2 anchor3 anchor4 anchor5 + +anchor1: + $(PRG) '^anchor1' test.mk + +anchor2: + $(PRG) 'Grep$$' test.mk + +# +# Find all empty lines. +# +anchor3: + $(PRG) '^$$' test.mk + +# +# This is valid but will never match. +# +anchor4: + -$(PRG) 'x^a' test.mk + +# +# This is valid but will never match. +# +anchor5: + -$(PRG) 'mk$$x' test.mk + +literal: literal1 literal2 + +# +# Every line with a dollar-sign. +# +literal1: + $(PRG) '\$$' test.mk + +# +# Every line with a backslash. +# +literal2: + $(PRG) '\\' test.mk + +# +# wild #1# +# wild #a# +# wild #%# +# +wild: + $(PRG) '#.#' test.mk + +# +# closure !! +# closure !x! +# closure !xxxxxx! +# +closure: + $(PRG) 'closure !x*!' test.mk + +# +# option ++ +# option +a+ +# option +b+ +# option +c+ +# option +abc+ +# +option: option1 option2 + +option1: + $(PRG) '+b?+' test.mk + +option2: + $(PRG) '+.?+' test.mk + +branch: branch1 branch2 branch3 branch4 branch5 branch6 + +branch1: + $(PRG) 'q|simple' test.mk + +# +# This pattern should be the same as '(^all)|(Public)|(Grep$)'. +# +branch2: + $(PRG) '^all|Public|Grep$$' test.mk + +# +# This pattern should generate the same results as branch2. +# +branch3: + $(PRG) 'Grep$|^all|Public' test.mk + +# +# Null expression between start of pattern and vertical-line. +# +branch4: + $(PRG) '|Grep' test.mk + +# +# Null expression between vertical-line and end of pattern. +# +branch5: + $(PRG) 'Grep|' test.mk + +# +# Null expression between vertical-line and vertical-line. +# +branch6: + $(PRG) 'all||Grep' test.mk + +# +# sub aabcbcbcxx +# sub aagxx +# sub aaggxx +# sub aadddxx +# sub aaxx +# +sub: sub0 sub1 sub2 sub3 sub4 sub5 lparen1 lparen2 rparen1 rparen2 + +# +# Null sub-expressions. +# +sub0: + $(PRG) 's()u()b()' test.mk + +sub1: + $(PRG) '#(1|%)#' test.mk + +sub2: + $(PRG) 'aa((bc)*|g)xx' test.mk + +# +# Null expression between the left-parenthesis and the vertical-line. +# +sub3: + $(PRG) '#(|1)#' test.mk + +# +# Null expression between the vertical-line and the right-parenthesis. +# +sub4: + $(PRG) '#(1|)#' test.mk + +# +# Null expression between the vertical-line and the right-parenthesis. +# +sub5: + $(PRG) '#(%||1)#' test.mk + +# +# Missing left-parenthesis generates an error. +# +lparen1: + -$(PRG) 'left ( only' test.mk + +lparen2: + $(PRG) 'left \( only' test.mk + +# +# Right-parenthesis without preceding left parenthesis should be a literal. +# +rparen1: + -$(PRG) 'right ) only' test.mk + +rparen2: + $(PRG) 'right \) only' test.mk + +# +# 12345678 +# ----------------- +# =0= 1 45 +# =1= 2 45 78 +# =2= 2 45 +# =3= 2 45 78 +# =4= 2 45 +# =5= 2 45 +# =6= 2 45 +# =7= 2 45 +# =8= 2 45 +# =9= 1 45 +# =]= 23 6 +# =-= 2 4 678 +# = = 2 4 6 +# +class: class1 class2 class3 class4 class5 class6 class7 class8 + +class1: + $(PRG) '=[09]=' test.mk + +class2: + $(PRG) '=[^09]=' test.mk + +class3: + $(PRG) '=[]]=' test.mk + +class4: + $(PRG) '=[^]]=' test.mk + +class5: + $(PRG) '=[0-9]=' test.mk + +class6: + $(PRG) '=[^0-9]=' test.mk + +class7: + -$(PRG) '=[3-1]=' test.mk + +class8: + $(PRG) '=[-13]=' test.mk + diff --git a/1993/ant/index.html b/1993/ant/index.html index 62877571a..7d4f16c9c 100644 --- a/1993/ant/index.html +++ b/1993/ant/index.html @@ -403,6 +403,8 @@ Location: CA - Canada

      To build:

          make all
      +

      The author provided a deobfuscated version. See Alternate +code below.

      Bugs and (Mis)features:

      The current status of this entry is:

          STATUS: INABIAF - please DO NOT fix
      @@ -412,6 +414,17 @@ Location: CA - Canada
       
          ./ant 'ERE' [file ...]

      Try:

          ./try.sh
      +

      Alternate code:

      +

      The ant.c in deobfuscated/ is a +deobfuscated version provided by the author. You can look at this code if you +want some clues in how it works.

      +

      Alternate build:

      +

      If you wish to build this deobfuscated version, you can do so like:

      +
          make alt
      +

      Alternate use:

      +

      Use ant.alt like you would ant above.

      +

      Alternate try:

      +
          ./try.alt.sh

      Judges’ remarks:

      See the author’s POSIX P1003.2-like documentation file ant.txt for more information.

      @@ -459,8 +472,14 @@ more information.

    • ant.orig.c - original source code
    • ant.txt - ag man page
    • try.sh - script to try entry
    • +
    • deobfuscated/ant-c89.c - author provided deobfuscated code converted from K&R
    • +
    • deobfuscated/ant.c - author provided deobfuscated code
    • +
    • try.alt.sh - script to try deobfuscated code
    • +
    • deobfuscated/Makefile - author provided Makefile for deobfuscated code
    • +
    • deobfuscated/test.mk - author provided test suite Makefile for deobfuscated code
    • ants.txt - lyrics of the Ants Go Marching song
    • ant.test.mk - test suite Makefile
    • +
    • ant.alt.test.mk - test suite Makefile for deobfuscated code

    Secondary files

      diff --git a/1993/ant/try.alt.sh b/1993/ant/try.alt.sh new file mode 100755 index 000000000..14ef530ae --- /dev/null +++ b/1993/ant/try.alt.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash +# +# try.sh - demonstrate IOCCC entry 1993/ant alt code +# + +# make sure CC is set so that when we do make CC="$CC" it isn't empty. Doing it +# this way allows us to have the user specify a different compiler in an easy +# way. +if [[ -z "$CC" ]]; then + CC="cc" +fi + +make CC="$CC" alt >/dev/null || exit 1 + +# clear screen after compilation so that only the entry is shown +clear + +read -r -n 1 -p "Press any key to run: ./ant.alt ant.alt README.md: " +echo 1>&2 +./ant.alt ant.alt README.md +echo 1>&2 + +read -r -n 1 -p "Press any key to run: ./ant.alt '\[' ant.txt: " +echo 1>&2 +./ant.alt '\[' ant.txt +echo 1>&2 + +echo "Note: the next one should show: ag: Pattern too long." 1>&2 +read -r -n 1 -p "Press any key to run: ./ant.alt '[' ant.txt: " +echo 1>&2 +./ant.alt '[' ant.txt +echo 1>&2 + +read -r -n 1 -p "Press any key to run: ./ant.alt ant ants.txt | cut -d: -f2 (space = next page, q = quit): " +echo 1>&2 +./ant.alt ant ants.txt | cut -d: -f2 | less -rEXF +echo 1>&2 + +read -r -n 1 -p "Press any key to run the test suite (make -f ant.alt.test.mk): " +echo 1>&2 +make -f ant.alt.test.mk diff --git a/1993/ant/try.sh b/1993/ant/try.sh index d355ddc71..05e091a9b 100755 --- a/1993/ant/try.sh +++ b/1993/ant/try.sh @@ -36,6 +36,6 @@ echo 1>&2 ./ant ant ants.txt | cut -d: -f2 | less -rEXF echo 1>&2 -read -r -n 1 -p "Press any key to run the test suite (make -f ant.test.mk) (space = next page, q = quit): " +read -r -n 1 -p "Press any key to run the test suite (make -f ant.test.mk): " echo 1>&2 -make -f ant.test.mk | less -rEXF +make -f ant.test.mk diff --git a/thanks-for-help.html b/thanks-for-help.html index 1f300e919..c60ca3dec 100644 --- a/thanks-for-help.html +++ b/thanks-for-help.html @@ -1408,9 +1408,21 @@ been fixed so that if one passes no arg it will still likely crash.

      Winning entry: 1991/ant

      Winning entry source code: ant.c

      -

      Cody added alternate code that will be a bit easier to use for -those familiar with vim in the following ways (we don’t want vi users to also -not be able to use it or exit it, now do we ? :-) ):

      +

      The author, Anthony C Howe, provided a +deobfuscated version which was put in by Cody with thanks to Anthony! +The deobfuscated directory has the code and Makefile. The entry’s Makefile was +updated to compile the alt code, if make alt is used, but in a way that keeps +both directories clean (the deobfuscated version will not be in the entry’s +directory and vice versa) but also allowing one to just do ./ant.alt2 (see +below for why alt2). There are two versions here, +deobfuscated/ant.c and +deobfuscated/ant-c89.c along +with the Makefile. The latter C file was converted from K&R by Anthony (the +other one did not compile without a few fixes made by Cody).

      +

      Cody also added alternate code that +will be a bit easier to use for those familiar with vim in the following ways +(we don’t want vi users to also not be able to use it or exit it, now do we ? +:-) ):

      • Use 0 to go to first column.
      • Use $ to go to last column.
      • @@ -1420,6 +1432,7 @@ not be able to use it or exit it, now do we ? :-) ):

      • Use q to exit.

      The other keys were left unchanged.

      +

      (As this was done first it was left as alt and not changed to alt2.)

      Winning entry: 1991/brnstnd

      Winning entry source code: brnstnd.c

      @@ -1691,6 +1704,15 @@ rule where a line was not ended with a \ but should have been.

      necessary to include time.h so Cody did this as well as this exists in other systems too.

      Cody also added the try.sh script.

      +

      The author, Anthony C Howe, provided a +deobfuscated version that Cody added in, with thanks to Anthony! The source code +and the Makefile as well as sleep.c are in the deobfuscated/ directory. +The entry’s Makefile was updated in a way that keeps the deobfuscated code +separate from the entry’s code but which allows one to use the deobfuscated +Makefile when compiling the alt code (via make alt). For this version, +try.alt.sh was added and an alternate test +Makefile (along the lines of the author’s provided test Makefile) was added, +updated to use ant.alt.

      Winning entry: 1992/buzzard.1

      Winning entry source code: buzzard.1.c

      @@ -1856,6 +1878,13 @@ encourage you to try the original without two args :-)

      Cody added the try.sh script and a data file, ants.txt, full of ants for the script.

      +

      The author, Anthony C Howe, provided a +deobfuscated version that Cody added in, with thanks to Anthony! The source code +(which might have had to be fixed to compile with modern compilers whereas the +-c89 version was converted from K&R and worked without any fixes) and its +Makefile was put in the deobfuscated subdirectory to keep them separate. The +entry’s Makefile was updated so that it uses the deobfuscated version’s Makefile +but allowing one to run ./ant.alt.

      Winning entry: 1993/cmills

      Winning entry source code: cmills.c

      diff --git a/thanks-for-help.md b/thanks-for-help.md index 4fb7a681a..e07630bb0 100644 --- a/thanks-for-help.md +++ b/thanks-for-help.md @@ -1459,9 +1459,23 @@ Cody also added the [try.sh](%%REPO_URL%%/1990/westley/try.sh) script. ### Winning entry source code: [ant.c](%%REPO_URL%%/1991/ant/ant.c)
      -[Cody](#cody) added [alternate code](%%REPO_URL%%/1991/ant/ant.alt.c) that will be a bit easier to use for -those familiar with vim in the following ways (we don't want vi users to also -not be able to use it or exit it, now do we ? :-) ): + +The author, [Anthony C Howe](authors.html#Anthony_C_Howe), provided a +deobfuscated version which was put in by [Cody](#cody) with thanks to Anthony! +The `deobfuscated` directory has the code and Makefile. The entry's Makefile was +updated to compile the alt code, if `make alt` is used, but in a way that keeps +both directories clean (the deobfuscated version will not be in the entry's +directory and vice versa) but also allowing one to just do `./ant.alt2` (see +below for why `alt2`). There are two versions here, +[deobfuscated/ant.c](%%REPO_URL%%/1991/ant/deobfuscated/ant.c) and +[deobfuscated/ant-c89.c](%%REPO_URL%%/1991/ant/deobfuscated/ant-c89.c) along +with the `Makefile`. The latter C file was converted from `K&R` by Anthony (the +other one did not compile without a few fixes made by Cody). + +[Cody](#cody) also added [alternate code](%%REPO_URL%%/1991/ant/ant.alt.c) that +will be a bit easier to use for those familiar with vim in the following ways +(we don't want vi users to also not be able to use it or exit it, now do we ? +:-) ): - Use `0` to go to first column. - Use `$` to go to last column. @@ -1472,6 +1486,8 @@ not be able to use it or exit it, now do we ? :-) ): The other keys were left unchanged. +(As this was done first it was left as `alt` and not changed to `alt2`.) +
      ## Winning entry: [1991/brnstnd](1991/brnstnd/index.html) @@ -1872,6 +1888,16 @@ systems too. Cody also added the [try.sh](%%REPO_URL%%/1992/ant/try.sh) script. +The author, [Anthony C Howe](authors.html#Anthony_C_Howe), provided a +deobfuscated version that Cody added in, with thanks to Anthony! The source code +and the `Makefile` as well as `sleep.c` are in the `deobfuscated/` directory. +The entry's Makefile was updated in a way that keeps the deobfuscated code +separate from the entry's code but which allows one to use the deobfuscated +Makefile when compiling the alt code (via `make alt`). For this version, +[try.alt.sh](%%REPO_URL%%/1992/ant/try.alt.sh) was added and an alternate test +Makefile (along the lines of the author's provided test Makefile) was added, +updated to use `ant.alt`. +
      ## Winning entry: [1992/buzzard.1](1992/buzzard.1/index.html) @@ -2096,6 +2122,14 @@ encourage you to try the original without two args :-) [Cody](#cody) added the [try.sh](%%REPO_URL%%/1993/ant/try.sh) script and a data file, [ants.txt](1993/ant/ants.txt), full of ants for the script. +The author, [Anthony C Howe](authors.html#Anthony_C_Howe), provided a +deobfuscated version that Cody added in, with thanks to Anthony! The source code +(which might have had to be fixed to compile with modern compilers whereas the +`-c89` version was converted from `K&R` and worked without any fixes) and its +Makefile was put in the `deobfuscated` subdirectory to keep them separate. The +entry's Makefile was updated so that it uses the deobfuscated version's Makefile +but allowing one to run `./ant.alt`. +
      ## Winning entry: [1993/cmills](1993/cmills/index.html) diff --git a/tmp/manifest.csv b/tmp/manifest.csv index 1a10e7f13..f0515913d 100644 --- a/tmp/manifest.csv +++ b/tmp/manifest.csv @@ -572,6 +572,9 @@ 1991,ant,Makefile,30,true,makefile,true,entry Makefile 1991,ant,ant.alt.c,40,true,c,true,alternate source code 1991,ant,ant.orig.c,50,false,c,true,original source code +1991,ant,deobfuscated/ant.c,140,true,c,true,author provided deobfuscated code +1991,ant,deobfuscated/ant-c89.c,140,true,c,true,author provided deobfuscated code converted from K&R +1991,ant,deobfuscated/Makefile,150,true,c,true,author provided Makefile for deobfuscated code 1991,ant,1991_ant.tar.bz2,1415926535,false,tbz2,false,download entry tarball 1991,ant,README.md,4000000000,true,markdown,true,markdown source for this web page 1991,ant,.entry.json,4000000000,true,json,true,entry summary and manifest in JSON @@ -709,8 +712,13 @@ 1992,ant,Makefile,30,true,makefile,true,entry Makefile 1992,ant,ant.orig.c,50,false,c,true,original source code 1992,ant,try.sh,100,true,shellscript,true,script to try entry +1992,ant,deobfuscated/ant.c,140,true,c,true,author provided deobfuscated code +1992,ant,deobfuscated/sleep.c,140,true,c,true,author provided code for those who need a nap 1992,ant,ant.README.txt,150,true,text,true,am man page 1992,ant,ant.test.mk,150,true,makefile,true,Makefile to demonstrate entry +1992,ant,deobfuscated/Makefile,150,true,makefile,true,author provided Makefile for deobfuscated code +1992,ant,try.alt.sh,150,true,shellscript,true,script to try deobfuscated code +1992,ant,ant.test.alt.mk,160,true,makefile,true,Makefile to demonstrate deobfuscated code 1992,ant,1992_ant.tar.bz2,1415926535,false,tbz2,false,download entry tarball 1992,ant,README.md,4000000000,true,markdown,true,markdown source for this web page 1992,ant,.entry.json,4000000000,true,json,true,entry summary and manifest in JSON @@ -840,8 +848,14 @@ 1993,ant,ant.orig.c,50,false,c,true,original source code 1993,ant,ant.txt,100,true,text,false,ag man page 1993,ant,try.sh,100,true,shellscript,true,script to try entry -1993,ant,ants.txt,150,true,text,false,lyrics of the Ants Go Marching song +1993,ant,deobfuscated/ant.c,120,true,c,true,author provided deobfuscated code +1993,ant,deobfuscated/ant-c89.c,120,true,c,true,author provided deobfuscated code converted from K&R +1993,ant,try.alt.sh,130,true,shellscript,true,script to try deobfuscated code +1993,ant,deobfuscated/Makefile,140,true,makefile,true,author provided Makefile for deobfuscated code +1993,ant,deobfuscated/test.mk,140,true,makefile,true,author provided test suite Makefile for deobfuscated code +1993,ant,ants.txt,150,false,text,false,lyrics of the Ants Go Marching song 1993,ant,ant.test.mk,150,true,makefile,true,test suite Makefile +1993,ant,ant.alt.test.mk,160,true,makefile,true,test suite Makefile for deobfuscated code 1993,ant,1993_ant.tar.bz2,1415926535,false,tbz2,false,download entry tarball 1993,ant,README.md,4000000000,true,markdown,true,markdown source for this web page 1993,ant,.entry.json,4000000000,true,json,true,entry summary and manifest in JSON diff --git a/tmp/manifest.numbers b/tmp/manifest.numbers index 42a4813e7..fd72f7fd4 100644 Binary files a/tmp/manifest.numbers and b/tmp/manifest.numbers differ diff --git a/tmp/path_list.built.txt b/tmp/path_list.built.txt index c1bfc4711..1f2a9c1f5 100644 --- a/tmp/path_list.built.txt +++ b/tmp/path_list.built.txt @@ -291,6 +291,7 @@ 1993/ant/.path 1993/ant/1993_ant.tar.bz2 1993/ant/ant.orig.c +1993/ant/ants.txt 1993/ant/index.html 1993/cmills/.path 1993/cmills/1993_cmills.tar.bz2 diff --git a/tmp/path_list.found.txt b/tmp/path_list.found.txt index c04b4ac0e..e840fcd71 100644 --- a/tmp/path_list.found.txt +++ b/tmp/path_list.found.txt @@ -576,6 +576,9 @@ 1991/ant/ant.alt.c 1991/ant/ant.c 1991/ant/ant.orig.c +1991/ant/deobfuscated/Makefile +1991/ant/deobfuscated/ant-c89.c +1991/ant/deobfuscated/ant.c 1991/ant/index.html 1991/brnstnd/.entry.json 1991/brnstnd/.gitignore @@ -713,8 +716,13 @@ 1992/ant/ant.README.txt 1992/ant/ant.c 1992/ant/ant.orig.c +1992/ant/ant.test.alt.mk 1992/ant/ant.test.mk +1992/ant/deobfuscated/Makefile +1992/ant/deobfuscated/ant.c +1992/ant/deobfuscated/sleep.c 1992/ant/index.html +1992/ant/try.alt.sh 1992/ant/try.sh 1992/buzzard.1/.entry.json 1992/buzzard.1/.gitignore @@ -840,12 +848,18 @@ 1993/ant/1993_ant.tar.bz2 1993/ant/Makefile 1993/ant/README.md +1993/ant/ant.alt.test.mk 1993/ant/ant.c 1993/ant/ant.orig.c 1993/ant/ant.test.mk 1993/ant/ant.txt 1993/ant/ants.txt +1993/ant/deobfuscated/Makefile +1993/ant/deobfuscated/ant-c89.c +1993/ant/deobfuscated/ant.c +1993/ant/deobfuscated/test.mk 1993/ant/index.html +1993/ant/try.alt.sh 1993/ant/try.sh 1993/cmills/.entry.json 1993/cmills/.gitignore diff --git a/tmp/path_list.manifest.txt b/tmp/path_list.manifest.txt index c04b4ac0e..e840fcd71 100644 --- a/tmp/path_list.manifest.txt +++ b/tmp/path_list.manifest.txt @@ -576,6 +576,9 @@ 1991/ant/ant.alt.c 1991/ant/ant.c 1991/ant/ant.orig.c +1991/ant/deobfuscated/Makefile +1991/ant/deobfuscated/ant-c89.c +1991/ant/deobfuscated/ant.c 1991/ant/index.html 1991/brnstnd/.entry.json 1991/brnstnd/.gitignore @@ -713,8 +716,13 @@ 1992/ant/ant.README.txt 1992/ant/ant.c 1992/ant/ant.orig.c +1992/ant/ant.test.alt.mk 1992/ant/ant.test.mk +1992/ant/deobfuscated/Makefile +1992/ant/deobfuscated/ant.c +1992/ant/deobfuscated/sleep.c 1992/ant/index.html +1992/ant/try.alt.sh 1992/ant/try.sh 1992/buzzard.1/.entry.json 1992/buzzard.1/.gitignore @@ -840,12 +848,18 @@ 1993/ant/1993_ant.tar.bz2 1993/ant/Makefile 1993/ant/README.md +1993/ant/ant.alt.test.mk 1993/ant/ant.c 1993/ant/ant.orig.c 1993/ant/ant.test.mk 1993/ant/ant.txt 1993/ant/ants.txt +1993/ant/deobfuscated/Makefile +1993/ant/deobfuscated/ant-c89.c +1993/ant/deobfuscated/ant.c +1993/ant/deobfuscated/test.mk 1993/ant/index.html +1993/ant/try.alt.sh 1993/ant/try.sh 1993/cmills/.entry.json 1993/cmills/.gitignore diff --git a/tmp/path_list.required.txt b/tmp/path_list.required.txt index 469caf332..2cbccb8b1 100644 --- a/tmp/path_list.required.txt +++ b/tmp/path_list.required.txt @@ -370,6 +370,9 @@ 1991/ant/README.md 1991/ant/ant.alt.c 1991/ant/ant.c +1991/ant/deobfuscated/Makefile +1991/ant/deobfuscated/ant-c89.c +1991/ant/deobfuscated/ant.c 1991/brnstnd/.entry.json 1991/brnstnd/.gitignore 1991/brnstnd/Makefile @@ -463,7 +466,12 @@ 1992/ant/README.md 1992/ant/ant.README.txt 1992/ant/ant.c +1992/ant/ant.test.alt.mk 1992/ant/ant.test.mk +1992/ant/deobfuscated/Makefile +1992/ant/deobfuscated/ant.c +1992/ant/deobfuscated/sleep.c +1992/ant/try.alt.sh 1992/ant/try.sh 1992/buzzard.1/.entry.json 1992/buzzard.1/.gitignore @@ -548,10 +556,15 @@ 1993/ant/.gitignore 1993/ant/Makefile 1993/ant/README.md +1993/ant/ant.alt.test.mk 1993/ant/ant.c 1993/ant/ant.test.mk 1993/ant/ant.txt -1993/ant/ants.txt +1993/ant/deobfuscated/Makefile +1993/ant/deobfuscated/ant-c89.c +1993/ant/deobfuscated/ant.c +1993/ant/deobfuscated/test.mk +1993/ant/try.alt.sh 1993/ant/try.sh 1993/cmills/.entry.json 1993/cmills/.gitignore