Bug fix and add alt code to 2005/anon

Previously the alt rule in the Makefile defined NO_STTY which stops the
code from using stty(1) at the beginning and at the end. The stty sane
resulted in a bus error in macOS and since the sole purpose was to set
echo back on I changed it to stty echo (which works). (The NO_STTY macro
is still checked, see below.)

Added alt code with vi(m) like movements.

The way to get it to not use stty is to use either make alt-no_stty or
no_stty. The former will compile into anon.alt and the latter will
compile into anon.

Format and typo fix README.md file.
This commit is contained in:
Cody Boone Ferguson committed 2023-11-20 10:45:10 -08:00
1 parent 86b6b2e41e
commit d1a462593f
5 files changed
+306 -128

No files matched your search

+8 -3
View File
@@ -131,15 +131,20 @@ all: data ${TARGET}
${PROG}: ${PROG}.c ${PROG}: ${PROG}.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS} ${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
${PROG}.alt: ${PROG}.c no_stty: ${PROG}.c
${CC} ${CFLAGS} -DNO_STTY $< -o $@ ${LDFLAGS} ${CC} ${CFLAGS} -DNO_STTY $< -o ${PROG} ${LDFLAGS}
# alternative executable # alternative executable
# #
alt: data ${ALT_TARGET} alt: data ${ALT_TARGET}
@${TRUE} @${TRUE}
${PROG}.alt: ${PROG}.alt.c
${CC} ${CFLAGS} $< -o $@ ${LDFLAGS}
alt-no_stty: ${PROG}.alt.c
${CC} ${CFLAGS} -DNO_STTY $< -o ${PROG}.alt ${LDFLAGS}
# data files # data files
# #
data: ${DATA} data: ${DATA}
+111 -119
View File
@@ -4,8 +4,15 @@
make make
``` ```
NOTE: if your shell does not support `stty` then see the alternate version NOTE: there is an alternate version for vi(m) like movements. See [alternate
described in the section below. version](#alternate-code) below. If your terminal has problems with the
`stty(1)` commands try:
```sh
make anon-no_stty
```
This will compile [anon.c](anon.c) as `anon` to not use `stty(1)`.
### Bugs and (Mis)features: ### Bugs and (Mis)features:
@@ -33,17 +40,6 @@ For more detailed information see [2005 anon in bugs.md](/bugs.md#2005-anon).
./anon 3 3 3 ./anon 3 3 3
``` ```
### Alternate version:
To use this version:
```sh
make alt
```
Use `anon.alt` as you would `anon`.
After a very large number of moves this program will deliberately force itself After a very large number of moves this program will deliberately force itself
to destroy its runtime stack. This is the author's way to prevent you from being to destroy its runtime stack. This is the author's way to prevent you from being
frustrated (which might happen as it likes to create unsolvable puzzles just to frustrated (which might happen as it likes to create unsolvable puzzles just to
@@ -56,16 +52,16 @@ This is supposed to happen. As is written in the
That's not a bug, that's a feature. That's not a bug, that's a feature.
``` ```
If you want to see this in action you can easily do this with the alt version: If you want to see this in action you can easily do this:
```sh ```sh
yes 'please crash on me :-)' | ./anon.alt 4 4 yes 'please crash on me :-)' | ./anon 4 4
``` ```
What happens if you specify a larger board? For instance: What happens if you specify a larger board? For instance:
```sh ```sh
yes 'please crash on me :-)' | ./anon.alt 10 10 10 yes 'please crash on me :-)' | ./anon 10 10 10
``` ```
If you specify more than three args the program might also crash or do If you specify more than three args the program might also crash or do
@@ -73,6 +69,38 @@ something strange. This might also happen if you specify excessively large board
dimensions. Try `100 100 100` for instance and see what happens! dimensions. Try `100 100 100` for instance and see what happens!
## Alternate version:
The alternate version uses `vi(m)` like movement keys.
### Alternate build:
```sh
make alt
```
To compile the version without `stty(1)`:
```sh
make alt-no_stty
```
### Alternate use:
Use `anon.alt` as you would `anon` with the change in movements:
```
k | Move empty spot up
h | Move empty spot left
j | Move empty spot down
l | Move empty spot right
J | Move empty spot forwards
K | Move empty spot backwards
```
## Judges' remarks: ## Judges' remarks:
Taking the 4x4 board with 15 tiles to a whole new level, this entry takes this Taking the 4x4 board with 15 tiles to a whole new level, this entry takes this
@@ -152,7 +180,7 @@ o | Move empty spot backwards
``` ```
**NOTE:** as a measure of alleviating counter-productivity due to addiction to **NOTE:** as a measure of alleviating counter-productivity due to addiction to
this game, particularly for those hardcore gamers who insist on solving a\ this game, particularly for those hardcore gamers who insist on solving a
10x10x10 puzzle during work hours, and also to give an upper bound to user 10x10x10 puzzle during work hours, and also to give an upper bound to user
frustration when the program generates an unsolvable puzzle (which it does frustration when the program generates an unsolvable puzzle (which it does
roughly half the time, just to hook you), the program will, after a very large roughly half the time, just to hook you), the program will, after a very large
@@ -160,10 +188,11 @@ number of moves (which is system-specific) terminate itself by forcefully
destroying its own runtime stack. This will result in a core dump and/or an destroying its own runtime stack. This will result in a core dump and/or an
abnormal termination message; but this is a feature, not a bug! :-) abnormal termination message; but this is a feature, not a bug! :-)
### COMPILE NOTES ### COMPILE NOTES
This program complies with ANSI/C99. It uses ANSI terminal control sequences, This program complies with ANSI/C99. It uses ANSI terminal control sequences,
and so requires a terminal that understands ANSI sequences, such as vt100 or and so requires a terminal that understands ANSI sequences, such as VT100 or
xterm. xterm.
Some compilers may emit lots of warnings about how things ought to be Some compilers may emit lots of warnings about how things ought to be
@@ -181,6 +210,7 @@ recursion, among other things. :-)
See spoilers below for more notes about portability. See spoilers below for more notes about portability.
### ABOUT THE CODE ### ABOUT THE CODE
Clearly, the author is very, very confused. Although he has broken up the file Clearly, the author is very, very confused. Although he has broken up the file
@@ -191,17 +221,17 @@ something is clearly very, very wrong.
In fact, the closer you look at this code, the more you realize something is In fact, the closer you look at this code, the more you realize something is
horribly wrong with it. For example, why is it that the first statement in horribly wrong with it. For example, why is it that the first statement in
`main()` is a `return`? What do all those nested `do`-loops do? (pun intended) Why `main()` is a `return`? What do all those nested `do` loops do (pun intended)? Why
is the first statement inside the first `do`-loop a mere integer literal? Why is the first statement inside the first `do` loop a mere integer literal? Why
are there such strange statements, like that empty string on line 65, or that are there such strange statements, like that empty string on line 65, or that
isolated `||` on line 68? isolated `||` on line 68?
But wait... why aren't any statements terminated by semicolons? Why is there But wait... why aren't any statements terminated by semicolons? Why is there
only ONE semicolon in the entire program?! Why is the author opening nested only ONE semicolon in the entire program?! Why is the author opening nested
blocks by such strange things as `||` and `(`, and closing them by `||` and `))`? The blocks by such strange things as `||` and `(`, and closing them by `||` and `))`? The
`for`-loop isn't a `for`-loop! The `do`-loop isn't a `do`-loop! Or... are they? Well, `for` loop isn't a `for` loop! The `do` loop isn't a `do` loop! Or... are they? Well,
the `for`-loop is defined in terms of a `while`-loop. But wait, the `while` loop is the `for` loop is defined in terms of a `while` loop. But wait, the `while` loop is
defined in terms of the `do`-loop. And the `do`-loop is defined in terms of ... defined in terms of the `do` loop. And the `do` loop is defined in terms of ...
Huh??? Huh???
And that `switch` statement toward the end of the program... wait a minute, And that `switch` statement toward the end of the program... wait a minute,
@@ -217,7 +247,7 @@ expert, it is probably easier to understand the program in its original form.
(And even then.) But that's just so, so wrong... (And even then.) But that's just so, so wrong...
The entire program consists of a single expression, returned from `main()`. The entire program consists of a single expression, returned from `main()`.
There are no `if`-statements, no `for`-loops or any looping or control constructs There are no `if` statements, no `for` loops or any looping or control constructs
besides the `return`, in spite of the misleading appearance of the original besides the `return`, in spite of the misleading appearance of the original
source. :) Yes I know, this has been attempted before, using `?:` and the bad source. :) Yes I know, this has been attempted before, using `?:` and the bad
old comma operator. BUT this program does NOT use the `?:` operator, and there old comma operator. BUT this program does NOT use the `?:` operator, and there
@@ -255,58 +285,19 @@ on the following architectures:
It probably will also compile and work on many (all?) other \*nix platforms as It probably will also compile and work on many (all?) other \*nix platforms as
well. How does it achieve this incredible feat? well. How does it achieve this incredible feat?
### SPOILER ### SPOILER
. Read the following only if you give up figuring it out :-)
.
.
.
.
.
.
.
.
.
.
(Read the following only if you give up figuring it out :-) )
.
.
.
.
.
.
.
.
.
#### The Evil Hack #### The Evil Hack
The program (ab)uses an implicit assumption underlying practically all The program (ab)uses an implicit assumption underlying practically all
architectures, and that is that parameters to C functions are implicit local architectures, and that is that parameters to C functions are implicit local
variables allocated on the runtime stack. This runtime stack is a contiguous variables allocated on the runtime stack. This runtime stack is a contiguous
section of memory, and therefore, after N recursive calls of `main()` to itself, section of memory, and therefore, after `N` recursive calls of `main()` to
there is enough room on the stack to store whatever the program desires, so itself, there is enough room on the stack to store whatever the program desires,
long as it does not exceed the maximum stack size. so long as it does not exceed the maximum stack size.
(Theoretically, the runtime stack doesn't **have** to be contiguous... but all (Theoretically, the runtime stack doesn't **have** to be contiguous... but all
current architectures that are worth consideration make this assumption. I current architectures that are worth consideration make this assumption. I
@@ -316,32 +307,32 @@ theoretically it shouldn't even work in the first place.) :-)
There are two types of architectures the program must handle: those that There are two types of architectures the program must handle: those that
allocate the stack top-down, and those that allocate the stack bottom-up. The allocate the stack top-down, and those that allocate the stack bottom-up. The
program correctly detects this at runtime, and adjusts itself accordingly. program correctly detects this at runtime, and adjusts itself accordingly.
:-) (It is a simple matter of testing if the address of argc in a recursive :-) (It is a simple matter of testing if the address of `argc` in a recursive
call is greater or less than in the parent call.) call is greater or less than in the parent call.)
To avoid having to handle issues of int sizes, memory alignment, what exactly To avoid having to handle issues of `int` sizes, memory alignment, what exactly
is on the stack between successive locations of argc, etc., the program is on the stack between successive locations of `argc`, etc., the program
(ab)uses the fact that argc must necessarily be allocated on an aligned (ab)uses the fact that `argc` must necessarily be allocated on an aligned
address, and therefore, the range of memory between two `argc`s is aligned, and address, and therefore, the range of memory between two `argc`s is aligned, and
therefore safe to use as an array of longs.[\*] The program also compares the therefore safe to use as an array of `long`s.[\*] The program also compares the
pointers as `long*` pointers, so that it will not have to deal with mapping pointers as `long*` pointers, so that it will not have to deal with mapping
bytes to larger types. The initial memory allocation is done by recursively bytes to larger types. The initial memory allocation is done by recursively
calling `main()` until there is enough space on the stack (the exact number of calling `main()` until there is enough space on the stack (the exact number of
recursive calls is, of course, architecture-dependent). recursive calls is, of course, architecture-dependent).
[\*] long was chosen instead of int, in order to skirt around pointer-size [\*] `long` was chosen instead of `int`, in order to skirt around pointer-size
issues on architectures like ia64. It really can be made anything large enough issues on architectures like ia64. It really can be made anything large enough
to hold both ints and pointers. `:-)` to hold both `int`s and pointers. `:-)`
After the stack is deemed to have grown deep enough to be a sufficiently long After the stack is deemed to have grown deep enough to be a sufficiently `long`
array (pun intended), the program begins its real code. It uses argc to keep array (pun intended), the program begins its real code. It uses `argc` to keep
track of what it's supposed to be doing (since `main()` is the only function), track of what it's supposed to be doing (since `main()` is the only function),
and `argv` to point to the base of this array (which is computed differently and `argv` to point to the base of this array (which is computed differently
based on how the architecture allocates the stack). Since this fills up the based on how the architecture allocates the stack). Since this fills up the
only two variables in the program, everything else is stored in the `MASS` [\*\*] only two variables in the program, everything else is stored in the `MASS` [\*\*]
array. array.
[\*\*] for "Memory Allocated by Stack Smashing" `:-)` [\*\*] for "Memory Allocated by Stack Smashing" :-)
Note that from this point on, all bets are off as to what the contents of the Note that from this point on, all bets are off as to what the contents of the
runtime stack are below the current recursive call to `main()`. We are runtime stack are below the current recursive call to `main()`. We are
@@ -352,6 +343,7 @@ program doesn't need the comma operator. :-) (I was going to skirt around the
issue by indirectly calling `exit()`, such as via `bsearch()` or `raise()`, but I issue by indirectly calling `exit()`, such as via `bsearch()` or `raise()`, but I
was getting too close to the size limit.) was getting too close to the size limit.)
#### Some notes about the macros #### Some notes about the macros
In spite of the frightening appearance, it is probably easiest to understand In spite of the frightening appearance, it is probably easiest to understand
@@ -374,7 +366,7 @@ a pointer to the top-level `argc`, to compute the location of the top-level
`argv`. This is done before the rest of the `MASS` is used, since otherwise they `argv`. This is done before the rest of the `MASS` is used, since otherwise they
may be overwritten. may be overwritten.
`do(x,y)` has nothing to do with `do`-loops. :-) It defines a "state" in `main()`, `do(x,y)` has nothing to do with `do` loops. :-) It defines a "state" in `main()`,
essentially, what to do when `main()` is called with `argc` containing a essentially, what to do when `main()` is called with `argc` containing a
particular value. (This is why the user must never run the program with more particular value. (This is why the user must never run the program with more
than 3 arguments. :-) The state number is `x`, and `y` is the code. The program's than 3 arguments. :-) The state number is `x`, and `y` is the code. The program's
@@ -389,7 +381,7 @@ allocation. It's the only state that needs to return a value from the boolean
expression, since once the `MASS` is initialized any return value can simply be expression, since once the `MASS` is initialized any return value can simply be
stored in a well-known location in the `MASS`. stored in a well-known location in the `MASS`.
`if(p,q,r,s)` is, in fact, an if-statement. `:-)` It is equivalent to: `if(p,q,r,s)` is, in fact, an `if` statement. :-) It is equivalent to:
```c ```c
if (p) { q; r } else {s} if (p) { q; r } else {s}
@@ -401,7 +393,7 @@ expressions. Keep in mind that all statements are assumed to evaluate to
false. The proof that this macro in fact implements an `if-then-else` construct false. The proof that this macro in fact implements an `if-then-else` construct
is left as an exercise for the reader. is left as an exercise for the reader.
`while(x,y,z)` is actually a `while`-loop after all. :-) It implements the loop `while(x,y,z)` is actually a `while` loop after all. :-) It implements the loop
using, of course, recursive calls to `main()`. However, this macro doesn't using, of course, recursive calls to `main()`. However, this macro doesn't
actually run a `while` loop; it implements the loop in the state numbered `x`. It actually run a `while` loop; it implements the loop in the state numbered `x`. It
is used for defining a `while` loop, which can then be called from another state is used for defining a `while` loop, which can then be called from another state
@@ -409,7 +401,7 @@ using `f(x)`. (The reason we can't directly implement a `while` loop inside
another state ought to be clear: we can't recursively call `main()` to enter another state ought to be clear: we can't recursively call `main()` to enter
into the middle of a state.) into the middle of a state.)
However, it _is_ possible to implement a `for`-loop directly inside a state! The However, it _is_ possible to implement a `for` loop directly inside a state! The
`for(s,i,x,y,z,Z)` macro does exactly this. Well, actually, technically speaking `for(s,i,x,y,z,Z)` macro does exactly this. Well, actually, technically speaking
this macro can only be used as the last thing in a state, because it secretly this macro can only be used as the last thing in a state, because it secretly
closes the current state and opens a new one behind the programmer's back. closes the current state and opens a new one behind the programmer's back.
@@ -434,7 +426,7 @@ other_code;
``` ```
Note the "wrong" indentation in the former: the author prefers to write it Note the "wrong" indentation in the former: the author prefers to write it
that way, since the analogy to the usual `for`-loop is clearer. This is why it's that way, since the analogy to the usual `for` loop is clearer. This is why it's
easier to understand the pre-CPP code, since after CPP, the macro reshuffles easier to understand the pre-CPP code, since after CPP, the macro reshuffles
`some_code` after `other_code` so that it can close the current state and define `some_code` after `other_code` so that it can close the current state and define
the one containing the loop body. (Have I told you that the author of this the one containing the loop body. (Have I told you that the author of this
@@ -445,7 +437,7 @@ indentation.)
In spite of all appearances, `switch()` really is just a shorthand macro for In spite of all appearances, `switch()` really is just a shorthand macro for
reducing code size. The evil choice of macro name is just to instill more reducing code size. The evil choice of macro name is just to instill more
confusion into the would-be decipherer of this entry. :-) After all, `case()` confusion into the would-be decipherer of this entry. :-) After all, `case()`
really _is_ the equivalent of a case statement, implemented using `&&`, and really _is_ the equivalent of a `case` statement, implemented using `&&`, and
conveniently encapsulating code common to the cases in the only `switch` conveniently encapsulating code common to the cases in the only `switch`
statement in the program, which is the code that decides what to do with a statement in the program, which is the code that decides what to do with a
key press. What could be more fun than to define such a case in terms of a key press. What could be more fun than to define such a case in terms of a
@@ -458,25 +450,25 @@ program, and what the various state numbers are meant to do:
#### MASS usage map #### MASS usage map
``` ```
0 | Function return value 0 | Function return value
1 | Function argument 1\ 1 | Function argument 1
2 | Function argument 2\ 2 | Function argument 2
3 | Function argument 3\ 3 | Function argument 3
4 | Scratch register 1\ 4 | Scratch register 1
5 | Scratch register 2\ 5 | Scratch register 2
6 | Scratch register 3\ 6 | Scratch register 3
7 | Scratch register 4\ 7 | Scratch register 4
8 | Value of original argv :-)\ 8 | Value of original argv :-)
9 | Value of original argc :-)\ 9 | Value of original argc :-)
11 | Zero register (always set to 0)\ 11 | Zero register (always set to 0)
12 | Width of board\ 12 | Width of board
13 | Length of board\ 13 | Length of board
14 | Height of board\ 14 | Height of board
15 | Current position of hole\ 15 | Current position of hole
16 | Random seed for rand_r()\ 16 | Random seed for rand_r(3)
18 | Scratch register used by state 18 :-)\ 18 | Scratch register used by state 18 :-)
31 | field width for printing tiles\ 31 | field width for printing tiles
32 | Start of board data\ 32 | Start of board data
``` ```
(**CAVEAT:** not all of these mappings ended up in the final version of the (**CAVEAT:** not all of these mappings ended up in the final version of the
@@ -492,22 +484,22 @@ to be on all tested architectures.)
#### State number assignments #### State number assignments
``` ```
1 | showhelp\ 1 | showhelp
2 | showhelp\ 2 | showhelp
3 | is 2D: start init\ 3 | is 2D: start init
4 | is 3D: start init\ 4 | is 3D: start init
5 | find allocation type\ 5 | find allocation type
6 | MASS init, bottom-up\ 6 | MASS init, bottom-up
7 | MASS init, top-down\ 7 | MASS init, top-down
8 | main program\ 8 | main program
9 | generate() outer loop\ 9 | generate() outer loop
13 | render()\ 13 | render()
14 | render() loop\ 14 | render() loop
15 | exit(0)\ 15 | exit(0)
16 | pick a tile that hasn't occurred yet\ 16 | pick a tile that hasn't occurred yet
17 | inner loop of 16.\ 17 | inner loop of 16.
18 | main loop\ 18 | main loop
19 | checkwin() loop\ 19 | checkwin() loop
``` ```
Note that some of the manually-implemented states (those not implemented by Note that some of the manually-implemented states (those not implemented by
+176
View File
@@ -0,0 +1,176 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
/* Defines */
#ifndef NO_STTY
#define S1 system("stty cbreak -echo")||
#define S2 system("stty echo")||
#else
#define S1
#define S2
#endif
#define A(i) (((q*)R(8))[i])
#define B p(b)
#define C p(&a)
#define H(i) sscanf(A(i),"%ld",&R(i+11))&0 ||
#define P q*
#define M(a,b) main((i)(a),(P)(b))
#define p(x) ((i*)(x))
#define D T(B-C,C-B)
#define T(x,y) ((a&1)*((i)(x))+(~a&1)*((i)(y)))
#define R(x) (*(B+x))
#define q char*
#define Q(x) ((q)(x))
#define W(x,y) ((B[x]=(i)(y))&0)||
#define BS (w*l*h)
#define do(x,y) (a-x||y)&&
#define f(x) M(x,b)
#define if(p,q,r,s) ((p)&&!(q)||(s))&&(r)||
#define i long
#define I (int)
#define while(x,y,z) do(x, y && !(z) && f(a))
#define for(s,i,x,y,z,Z) W(i,x)f(s)||Z) && while(s,R(i)-y,z||W(i,R(i)+1)0)(s
#define return return do
#define w R(12)
#define l R(13)
#define h R(14)
#define X(i) (R(i)%w)
#define Y(i) ((R(i)%(w*l))/w)
#define Z(i) (R(i)/(w*l))
#define pr !printf
#define switch(x) (W(32+R(15),R(32+x+R(15))) W(32+x+R(15),0) (B[15]+=x)|1)
#define case(k,x,y) R(a)==k && x && switch(y) && f(13)||
#define TL(i) R(32+R(i))
/* Main program */
int
main(int a, P b)
{
return (1 >> 1 ^ 1, M(6 + !!M(5, C), C))
do
(
13,
pr("\x1b[;H") ||
for (14, 4, 0, BS, !X(4) && pr(
"%*s",
I(l - Y(4)),
""
)
||
if (TL(4), pr(
"%*ld", I
R(31),
TL(4)), 0,
pr("%*.*s", I
R(31),
I R(31), "#####")
)
if (X(4) == w - 1, pr("\n"), 0, pr("%*s", I(l + 1), "")) (
(R(4) + 1) % (w * l) == 0 && l > 1) &&
pr("\n"), 0))
do
(
1 & ~1,
pr("Syntax: %s <x> <y> [<z>]\n", b[0]) || f(15)
) ((a & ~1)
- 6 || D >> 12
&& (*(p(T(C, b)) + 8) = *p(Q(b) + (Q(&b) - Q(C)))
)
&& (*(p(T(C, b)) + 9) = *p(b)) && M(
8, T(C, b))
||
f(a)) &&
do
(
8,
if (R(9) & 1, H(1) H(
2) 0, W(14,
l) W(13, 1) 0,
H(1
)
H(2)
H(3)
0) (srand(time(0)), 0
) || for (9, 4, 0, BS, f(16)
|| W(R(4) + 32, R(0)) ! R(0) && W(15, R(4)) 0,
W(
31,
snprintf(A(0), 1, "%ld", BS))
S1 pr("\x1b[2J") ||
f(13)
||
f(18) ||
f(15)
))
do
(
16, W(0, rand() % BS
) W(1, 0)
for (17, 5, 0, R(4), !(
TL(
5) - R(0)) && !(
W(1, 1)
W(5, R(4) - 1)
0), R(1) && f(16))
)
do
(
18, W(0, 0
) for (19, 4, 0, BS, TL(4) - (R(4) + 1)
% BS && (
W(0, 1)
W(4, BS - 1
) 0) || 0, !R(0) &&
pr(
"You win!\n"
)
||
R(0) && (
W(a, getchar())
case ('k',
0 < Z(15),
-w * l)
case ('h',
0 < X(15),
-1)
case ('j',
Z(15) < h - 1,
w * l)
case ('l',
X(15) < w - 1,
1)
case ('J',
Y(15) < l - 1,
w)
case ('K',
0 < Y(15), -w
)
R(a) == 'q' && !
pr(
"You lose :-)\n"
)
&& f(15) || f(a))
)
)
do
(
15, S2
(exit(0), a)
) (a - 5 || C < p(b));
}
+1 -1
View File
@@ -7,7 +7,7 @@
#ifndef NO_STTY #ifndef NO_STTY
#define S1 system("stty cbreak -echo")|| #define S1 system("stty cbreak -echo")||
#define S2 system("stty sane")|| #define S2 system("stty echo")||
#else #else
#define S1 #define S1
#define S2 #define S2
+10 -5
View File
@@ -2880,11 +2880,16 @@ suite.
## [2005/anon](2005/anon/anon.c) ([README.md](2005/anon/README.md])) ## [2005/anon](2005/anon/anon.c) ([README.md](2005/anon/README.md]))
The author stated that if `stty` does not work right on your system you can Cody fixed a problem where in some systems (like macOS) the `stty sane` would
compile it differently so that the program does not use `stty`. Cody set this not work and end up causing a bus error. Instead of `stty sane` it uses `stty
up so that one need not update the [Makefile](Makefile). There's a fun command echo` which is what it was trying to accomplish.
that Cody provided, to try, to see a feature that the author implemented. See
the README.md for details. The author noted that one can define `NO_STTY` to not use `stty(1)` at all
(either to prevent having to hit enter or to turn echo off/on) which is
explained in the README.md.
Cody added the [alt code](2005/anon/README.md#alternate-code) with vi(m) like
movements.
## [2005/giljade](2005/giljade/giljade.c) ([README.md](2005/giljade/README.md])) ## [2005/giljade](2005/giljade/giljade.c) ([README.md](2005/giljade/README.md]))