Merge pull request #2543 from xexyl/ant
This commit is contained in:
39 files changed
+3174
-48
No files matched your search
@@ -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,
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
*.dSYM
|
||||
ant
|
||||
ant.alt
|
||||
ant.alt2
|
||||
ant.alt2-c89
|
||||
ant.orig
|
||||
hill
|
||||
indent
|
||||
|
||||
+26
-3
@@ -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'; \
|
||||
|
||||
+21
-10
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,371 @@
|
||||
/*
|
||||
* Anthony's Editor
|
||||
*
|
||||
* Public Domain 1991, 2023 by Anthony Howe. All rights released.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <curses.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
@@ -0,0 +1,364 @@
|
||||
/*
|
||||
* ae.c Anthony's Editor IOCCC '91
|
||||
*
|
||||
* Public Domain 1991 by Anthony Howe. All rights released.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <curses.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
+23
-10
@@ -403,8 +403,9 @@ Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
<!-- BEFORE: 1st line of markdown file: 1991/ant/README.md -->
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<pre><code> make all</code></pre>
|
||||
<p>There is an <a href="#alternate-code">alternate version</a> that might feel a bit more
|
||||
familiar to vi(m) users.</p>
|
||||
<p>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 <a href="#alternate-code">Alternate code</a> below.</p>
|
||||
<h2 id="to-use">To use:</h2>
|
||||
<pre><code> ./ant some_file</code></pre>
|
||||
<p>NOTE: the file must already exist and not specifying any arg will make the
|
||||
@@ -415,19 +416,28 @@ program exit without doing anything.</p>
|
||||
<pre><code> make mole
|
||||
./ant mole</code></pre>
|
||||
<h2 id="alternate-code">Alternate code:</h2>
|
||||
<p>This version changes the commands slightly so that to go to the first column you
|
||||
should enter <code>0</code>, to go to the last column you should enter <code>$</code>, to quit you
|
||||
should enter <code>q</code>, to go back a word you should enter <code>b</code> and to go forwards a
|
||||
word you should enter <code>w</code>. Also, and perhaps most useful, rather than having to
|
||||
hit ctrl-L (form-feed, <code>\f</code>) to get back to command mode you can use the usual
|
||||
ESC (<code>\x1b</code>).</p>
|
||||
<p>The author provided us with deobfuscated versions including one for C89. The two
|
||||
C files in <code>deobfuscated</code>,
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/ant.c">deobfuscated/ant.c</a> and
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/ant-c89.c">deobfuscated/ant-c89.c</a> and the
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/Makefile">deobfuscated/Makefile</a> 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.</p>
|
||||
<p>The other version, <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/ant.alt.c">ant.alt.c</a> changes the
|
||||
commands slightly so that to go to the first column you should enter <code>0</code>, to go
|
||||
to the last column you should enter <code>$</code>, to quit you should enter <code>q</code>, to go
|
||||
back a word you should enter <code>b</code> and to go forwards a word you should enter <code>w</code>.
|
||||
Also, and perhaps most useful, rather than having to hit ctrl-L (form-feed,
|
||||
<code>\f</code>) to get back to command mode you can use the usual ESC (<code>\x1b</code>).</p>
|
||||
<p>These will make it slightly less unwieldy for those familiar with vi(m); the
|
||||
rest was unchanged.</p>
|
||||
<h3 id="alternate-build">Alternate build:</h3>
|
||||
<pre><code> make alt</code></pre>
|
||||
<h3 id="alternate-use">Alternate use:</h3>
|
||||
<p>Use <code>ant.alt</code> as you would <code>ant</code> above with the changes in the input keys. See
|
||||
the author’s remarks for the remaining keys.</p>
|
||||
<p>For the deobfuscated versions, use <code>ant.alt2</code> and <code>ant.alt2-c89</code> as you would
|
||||
<code>ant</code> above; for the other one, <code>ant.alt</code>, use it as you would <code>ant</code> above but
|
||||
with the changes in the input keys described above. See the author’s remarks for
|
||||
the remaining commands.</p>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<p>The author was kind enough to supply a list of references below,
|
||||
in case you are still confused after read the source! :-)</p>
|
||||
@@ -540,6 +550,9 @@ ISBN 0-13-822305-X, chapter 5</p>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/Makefile">Makefile</a> - entry Makefile</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/ant.alt.c">ant.alt.c</a> - alternate source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/ant.orig.c">ant.orig.c</a> - original source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/ant-c89.c">deobfuscated/ant-c89.c</a> - author provided deobfuscated code converted from K&R</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/ant.c">deobfuscated/ant.c</a> - author provided deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/Makefile">deobfuscated/Makefile</a> - author provided Makefile for deobfuscated code</li>
|
||||
</ul>
|
||||
<h2 id="secondary-files">Secondary files</h2>
|
||||
<ul>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
+33
-6
@@ -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}
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
```
|
||||
|
||||
|
||||
The author provided us with an unobfuscated version. See [Alternate
|
||||
code](#alternate-code) below.
|
||||
|
||||
|
||||
## To use:
|
||||
|
||||
``` <!---sh-->
|
||||
@@ -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:
|
||||
|
||||
``` <!---sh-->
|
||||
make alt
|
||||
```
|
||||
|
||||
|
||||
## Alternate use:
|
||||
|
||||
Use `ant.alt` as you would `ant` above.
|
||||
|
||||
|
||||
## Try:
|
||||
|
||||
``` <!---sh-->
|
||||
./try.alt.sh
|
||||
```
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
Like much of POSIX, obfuscation has its place. Your task is to
|
||||
|
||||
@@ -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.*
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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 $@
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* am.c Anthony's Make
|
||||
*
|
||||
* Public Domain 1992 by Anthony Howe. All rights released.
|
||||
*
|
||||
*
|
||||
* SYNOPSIS
|
||||
*
|
||||
* am <makefile> [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 <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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 <makefile> [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);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* sleep.c
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
|
||||
void
|
||||
sleep(secs)
|
||||
unsigned secs;
|
||||
{
|
||||
clock_t start, now;
|
||||
|
||||
start = clock();
|
||||
do
|
||||
now = clock();
|
||||
while ((now - start) / CLK_TCK < secs);
|
||||
}
|
||||
|
||||
@@ -403,6 +403,8 @@ Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
<!-- BEFORE: 1st line of markdown file: 1992/ant/README.md -->
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<pre><code> make all</code></pre>
|
||||
<p>The author provided us with an unobfuscated version. See <a href="#alternate-code">Alternate
|
||||
code</a> below.</p>
|
||||
<h2 id="to-use">To use:</h2>
|
||||
<pre><code> ./ant Makefile
|
||||
|
||||
@@ -410,6 +412,15 @@ Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
<p>where <code>Makefile</code> is a Makefile to use and <code>rule</code> is an optional rule to use.</p>
|
||||
<h2 id="try">Try:</h2>
|
||||
<pre><code> ./try.sh</code></pre>
|
||||
<h2 id="alternate-code">Alternate code:</h2>
|
||||
<p>This version, <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/deobfuscated/ant.c">ant.c in deobfuscated/</a>, was provided by the
|
||||
author in 2024, and is a deobfuscated version.</p>
|
||||
<h2 id="alternate-build">Alternate build:</h2>
|
||||
<pre><code> make alt</code></pre>
|
||||
<h2 id="alternate-use">Alternate use:</h2>
|
||||
<p>Use <code>ant.alt</code> as you would <code>ant</code> above.</p>
|
||||
<h2 id="try-1">Try:</h2>
|
||||
<pre><code> ./try.alt.sh</code></pre>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<p>Like much of POSIX, obfuscation has its place. Your task is to
|
||||
figure out where.</p>
|
||||
@@ -447,8 +458,13 @@ P1003 subcommittee.</p>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/Makefile">Makefile</a> - entry Makefile</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/ant.orig.c">ant.orig.c</a> - original source code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/try.sh">try.sh</a> - script to try entry</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/deobfuscated/ant.c">deobfuscated/ant.c</a> - author provided deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/deobfuscated/sleep.c">deobfuscated/sleep.c</a> - author provided code for those who need a nap</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/ant.README.txt">ant.README.txt</a> - am man page</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/ant.test.mk">ant.test.mk</a> - Makefile to demonstrate entry</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/deobfuscated/Makefile">deobfuscated/Makefile</a> - author provided Makefile for deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/try.alt.sh">try.alt.sh</a> - script to try deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/ant.test.alt.mk">ant.test.alt.mk</a> - Makefile to demonstrate deobfuscated code</li>
|
||||
</ul>
|
||||
<h2 id="secondary-files">Secondary files</h2>
|
||||
<ul>
|
||||
|
||||
Executable
+35
@@ -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
|
||||
+49
-1
@@ -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,
|
||||
|
||||
@@ -2,8 +2,10 @@
|
||||
# sort with: ../../bin/sgi.sh
|
||||
*.dSYM
|
||||
ag
|
||||
ag.alt
|
||||
ag.txt
|
||||
ant
|
||||
ant.alt
|
||||
ant.orig
|
||||
indent
|
||||
indent.c
|
||||
|
||||
+26
-5
@@ -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'; \
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
``` <!---sh-->
|
||||
make alt
|
||||
```
|
||||
|
||||
|
||||
## Alternate use:
|
||||
|
||||
Use `ant.alt` like you would `ant` above.
|
||||
|
||||
|
||||
## Alternate try:
|
||||
|
||||
``` <!---sh-->
|
||||
./try.alt.sh
|
||||
```
|
||||
|
||||
|
||||
## Judges' remarks:
|
||||
|
||||
See the author's POSIX P1003.2-like documentation file [ant.txt](ant.txt) for
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* ag.c
|
||||
*
|
||||
* Anthony's Grep
|
||||
*
|
||||
* Public Domain 1992, 2021 by Anthony Howe. All rights released.
|
||||
*
|
||||
* Synopsis: ag <pattern> [files...]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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 <pattern> [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);
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* ag.c
|
||||
*
|
||||
* Anthony's Grep
|
||||
*
|
||||
* Public Domain 1992, 1993 by Anthony Howe. All rights released.
|
||||
*
|
||||
* Synopsis: ag <pattern> [files...]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#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 <pattern> [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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -403,6 +403,8 @@ Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
<!-- BEFORE: 1st line of markdown file: 1993/ant/README.md -->
|
||||
<h2 id="to-build">To build:</h2>
|
||||
<pre><code> make all</code></pre>
|
||||
<p>The author provided a deobfuscated version. See <a href="#alternate-code">Alternate
|
||||
code</a> below.</p>
|
||||
<h3 id="bugs-and-misfeatures">Bugs and (Mis)features:</h3>
|
||||
<p>The current status of this entry is:</p>
|
||||
<pre><code> STATUS: INABIAF - please DO NOT fix
|
||||
@@ -412,6 +414,17 @@ Location: <a href="../../location.html#CA">CA</a> - <em>Canada</em></li>
|
||||
<pre><code> ./ant 'ERE' [file ...]</code></pre>
|
||||
<h2 id="try">Try:</h2>
|
||||
<pre><code> ./try.sh</code></pre>
|
||||
<h2 id="alternate-code">Alternate code:</h2>
|
||||
<p>The <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/deobfuscated/ant.c">ant.c in deobfuscated/</a> is a
|
||||
deobfuscated version provided by the author. You can look at this code if you
|
||||
want some clues in how it works.</p>
|
||||
<h2 id="alternate-build">Alternate build:</h2>
|
||||
<p>If you wish to build this deobfuscated version, you can do so like:</p>
|
||||
<pre><code> make alt</code></pre>
|
||||
<h2 id="alternate-use">Alternate use:</h2>
|
||||
<p>Use <code>ant.alt</code> like you would <code>ant</code> above.</p>
|
||||
<h2 id="alternate-try">Alternate try:</h2>
|
||||
<pre><code> ./try.alt.sh</code></pre>
|
||||
<h2 id="judges-remarks">Judges’ remarks:</h2>
|
||||
<p>See the author’s POSIX P1003.2-like documentation file <a href="ant.txt">ant.txt</a> for
|
||||
more information.</p>
|
||||
@@ -459,8 +472,14 @@ more information.</p>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/ant.orig.c">ant.orig.c</a> - original source code</li>
|
||||
<li><a href="ant.txt">ant.txt</a> - ag man page</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/try.sh">try.sh</a> - script to try entry</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/deobfuscated/ant-c89.c">deobfuscated/ant-c89.c</a> - author provided deobfuscated code converted from K&R</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/deobfuscated/ant.c">deobfuscated/ant.c</a> - author provided deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/try.alt.sh">try.alt.sh</a> - script to try deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/deobfuscated/Makefile">deobfuscated/Makefile</a> - author provided Makefile for deobfuscated code</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/deobfuscated/test.mk">deobfuscated/test.mk</a> - author provided test suite Makefile for deobfuscated code</li>
|
||||
<li><a href="ants.txt">ants.txt</a> - lyrics of the Ants Go Marching song</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/ant.test.mk">ant.test.mk</a> - test suite Makefile</li>
|
||||
<li><a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/ant.alt.test.mk">ant.alt.test.mk</a> - test suite Makefile for deobfuscated code</li>
|
||||
</ul>
|
||||
<h2 id="secondary-files">Secondary files</h2>
|
||||
<ul>
|
||||
|
||||
Executable
+41
@@ -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
|
||||
+2
-2
@@ -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
|
||||
+32
-3
@@ -1408,9 +1408,21 @@ been fixed so that if one passes no arg it will still likely crash.</p>
|
||||
<h2 id="winning-entry-1991ant">Winning entry: <a href="1991/ant/index.html">1991/ant</a></h2>
|
||||
<h3 id="winning-entry-source-code-ant.c">Winning entry source code: <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/ant.c">ant.c</a></h3>
|
||||
</div>
|
||||
<p><a href="#cody">Cody</a> added <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/ant.alt.c">alternate code</a> 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 ? :-) ):</p>
|
||||
<p>The author, <a href="authors.html#Anthony_C_Howe">Anthony C Howe</a>, provided a
|
||||
deobfuscated version which was put in by <a href="#cody">Cody</a> with thanks to Anthony!
|
||||
The <code>deobfuscated</code> directory has the code and Makefile. The entry’s Makefile was
|
||||
updated to compile the alt code, if <code>make alt</code> 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 <code>./ant.alt2</code> (see
|
||||
below for why <code>alt2</code>). There are two versions here,
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/ant.c">deobfuscated/ant.c</a> and
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/deobfuscated/ant-c89.c">deobfuscated/ant-c89.c</a> along
|
||||
with the <code>Makefile</code>. The latter C file was converted from <code>K&R</code> by Anthony (the
|
||||
other one did not compile without a few fixes made by Cody).</p>
|
||||
<p><a href="#cody">Cody</a> also added <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/ant/ant.alt.c">alternate code</a> 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 ?
|
||||
:-) ):</p>
|
||||
<ul>
|
||||
<li>Use <code>0</code> to go to first column.</li>
|
||||
<li>Use <code>$</code> to go to last column.</li>
|
||||
@@ -1420,6 +1432,7 @@ not be able to use it or exit it, now do we ? :-) ):</p>
|
||||
<li>Use <code>q</code> to exit.</li>
|
||||
</ul>
|
||||
<p>The other keys were left unchanged.</p>
|
||||
<p>(As this was done first it was left as <code>alt</code> and not changed to <code>alt2</code>.)</p>
|
||||
<div id="1991_brnstnd">
|
||||
<h2 id="winning-entry-1991brnstnd">Winning entry: <a href="1991/brnstnd/index.html">1991/brnstnd</a></h2>
|
||||
<h3 id="winning-entry-source-code-brnstnd.c">Winning entry source code: <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1991/brnstnd/brnstnd.c">brnstnd.c</a></h3>
|
||||
@@ -1691,6 +1704,15 @@ rule where a line was not ended with a <code>\</code> but should have been.</p>
|
||||
necessary to include <code>time.h</code> so Cody did this as well as this exists in other
|
||||
systems too.</p>
|
||||
<p>Cody also added the <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/try.sh">try.sh</a> script.</p>
|
||||
<p>The author, <a href="authors.html#Anthony_C_Howe">Anthony C Howe</a>, provided a
|
||||
deobfuscated version that Cody added in, with thanks to Anthony! The source code
|
||||
and the <code>Makefile</code> as well as <code>sleep.c</code> are in the <code>deobfuscated/</code> 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 <code>make alt</code>). For this version,
|
||||
<a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/ant/try.alt.sh">try.alt.sh</a> was added and an alternate test
|
||||
Makefile (along the lines of the author’s provided test Makefile) was added,
|
||||
updated to use <code>ant.alt</code>.</p>
|
||||
<div id="1992_buzzard.1">
|
||||
<h2 id="winning-entry-1992buzzard.1">Winning entry: <a href="1992/buzzard.1/index.html">1992/buzzard.1</a></h2>
|
||||
<h3 id="winning-entry-source-code-buzzard.1.c">Winning entry source code: <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1992/buzzard.1/buzzard.1.c">buzzard.1.c</a></h3>
|
||||
@@ -1856,6 +1878,13 @@ encourage you to try the original without two args :-)</p>
|
||||
</div>
|
||||
<p><a href="#cody">Cody</a> added the <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/ant/try.sh">try.sh</a> script and a data file,
|
||||
<a href="1993/ant/ants.txt">ants.txt</a>, full of ants for the script.</p>
|
||||
<p>The author, <a href="authors.html#Anthony_C_Howe">Anthony C Howe</a>, 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
|
||||
<code>-c89</code> version was converted from <code>K&R</code> and worked without any fixes) and its
|
||||
Makefile was put in the <code>deobfuscated</code> 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 <code>./ant.alt</code>.</p>
|
||||
<div id="1993_cmills">
|
||||
<h2 id="winning-entry-1993cmills">Winning entry: <a href="1993/cmills/index.html">1993/cmills</a></h2>
|
||||
<h3 id="winning-entry-source-code-cmills.c-1">Winning entry source code: <a href="https://github.com/ioccc-src/temp-test-ioccc/blob/master/1993/cmills/cmills.c">cmills.c</a></h3>
|
||||
|
||||
+37
-3
@@ -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)
|
||||
</div>
|
||||
|
||||
[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`.)
|
||||
|
||||
|
||||
<div id="1991_brnstnd">
|
||||
## 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`.
|
||||
|
||||
|
||||
<div id="1992_buzzard.1">
|
||||
## 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`.
|
||||
|
||||
|
||||
<div id="1993_cmills">
|
||||
## Winning entry: [1993/cmills](1993/cmills/index.html)
|
||||
|
||||
+15
-1
@@ -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
|
||||
|
||||
|
Binary file not shown.
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user