git @ Cat's Eye Technologies stringie / 1.0
Merge pull request #2 from catseye/develop-1.0 Develop 1.0 Chris Pressey authored 4 years ago GitHub committed 4 years ago
16 changed file(s) with 189 addition(s) and 17 deletion(s). Raw diff Collapse all Expand all
0 bin/
0 _UAEFSDB.___
1 bin/stringie
12 *.o
00 stringie
11 ========
22
3 This is the distribution for "stringie", an implementation of [Underload][] in ANSI C.
3 This is the distribution for "stringie", an implementation of [Underload][] in
4 ANSI C.
45
56 [Underload]: http://esolangs.org/wiki/Underload
67
78 History
89 -------
910
10 Seeing that there was no _non_-pathological implementation of ais523's beautiful
11 Underload language in C, I undertook that project one evening. (In the company of a
12 bottle of really fine wine. Why, it cost almost twelve dollars.) The result is one
13 of the most pedantic and boring Underload interpreters known to man. Perhaps the
14 most interesting property of it is its name, "stringie", which was an accident.
11 Seeing that there was no _non_-pathological implementation of ais523's
12 beautiful Underload language in C, I undertook that project one evening.
13 (In the company of a bottle of really fine wine. Why, it cost almost twelve
14 dollars.) The result is one of the most pedantic and boring Underload
15 interpreters known to man. Perhaps the most interesting property of it is its
16 name, "stringie", which was an accident.
1517
1618 Building
1719 --------
1820
1921 (cd src && make)
2022
21 You can also pass `ANSI=yes` to `make` to have the C compiler treat the source code
22 as ANSI C, and this will work, because the source code is ANSI C.
23 You can also pass `ANSI=yes` to `make` to have the C compiler treat the source
24 code as ANSI C, and this will work, because the source code is ANSI C.
25
26 It can also be build using DICE C under AmigaDOS 1.3; see the file
27 [build.seq](build.seq) for details.
2328
2429 Usage
2530 -----
2631
2732 ./bin/stringie '(Hello, world!)S'
2833
29 From this we can see that the Underload program to be interpreted is passed directly
30 in the first argument.
34 From this we can see that the Underload program to be interpreted is passed
35 directly in the first command-line argument to the executable.
36
37 However, there is also a form by which the Underload program can be read from
38 a file:
39
40 ./bin/stringie from eg/hello.ul
41
42 Included materials
43 ------------------
44
45 This distribution also contains a description of the Underload language
46 in the `doc` directory, and a collection of example programs in the `eg`
47 directory. These were taken from public-domain sources.
3148
3249 License
3350 -------
3451
35 The contents of this repository are in the public domain. See [UNLICENSE](UNLICENSE)
36 for more information.
52 The contents of this repository are in the public domain. See the file
53 [UNLICENSE](UNLICENSE) for more information.
54
55 Acknowledgements
56 ----------------
57
58 Thanks to [stasoid](https://github.com/stasoid) for finding, and describing a
59 fix for, [a heap-corrupting bug](https://github.com/catseye/Dipple/issues/2).
0 This directory is where compiled executables will be placed.
0 ;
1 ; To build the 'stringie' executable using DICE C
2 ; under AmigaDOS 1.3, you can either run
3 ;
4 ; protect build.seq srwd
5 ; build.seq
6 ;
7 ; or you can simply type the following commands into the shell:
8 ;
9 dcc -DAUTOFLUSH src/stringie.c -o bin/stringie
0 Underload
1 =========
2
3 (This document was converted from the public-domain
4 [HTML Underload specification][] in [The Esoteric File Archive][].)
5
6 Basics
7 ------
8
9 Underload is a stack-based programming language that works along similar
10 lines to Muriel. Although not technically speaking a functional
11 language, its evaluation operator `^` (which is the only form of flow
12 control) makes programming in it functional in practice.
13
14 Reserved characters
15 -------------------
16
17 The bracket and angle bracket characters []<> are reserved; if these are
18 to appear anywhere in the program, they must be quoted by placing "
19 before them. This also applies to the " character itself. Other
20 characters must _not_ be quoted with " (in particular, this means that
21 Underload programs cannot output strings containing unmatched
22 parentheses). Parentheses are moderately reserved, in that any Underload
23 program must have matched parentheses to be legal.
24
25 Commands
26 --------
27
28 - `~` Swap the top two elements of the stack.
29 - `:` Duplicate the top element of the stack.
30 - `!` Discard the top element of the stack.
31 - `*` Concatenate the top element of the stack to the end of the second
32 element of the stack.
33 - `(` Push everything between the `(` and the matching `)` on top of
34 the stack.
35 - `)` Closes a `(` command.
36 - `a` Encloses the top element of the stack in a pair of parentheses.
37 - `^` When the `^` command is called, it includes the top element of the
38 stack into the program, immediately after the `^` command, ready to be
39 run next.
40 - `S` Output the top element of the stack, popping it.
41
42 Exceptional circumstances
43 -------------------------
44
45 Pretty much anything whose behaviour isn't specifically given here (for
46 instance, running `*` on an empty stack) is an error.
47
48 Example programs
49 ----------------
50
51 ### Hello, world!
52
53 (Hello, world!)S
54
55 ### Fibonacci sequence
56
57 (()(*))(~:^:S*a~^a~!~*~:(/)S^):^
58
59 ### Infinite loop
60
61 (:^):^
62
63 ### Quine
64
65 (:aSS):aSS
66
67 (The null program is also a quine. This program is more stack-based than
68 functional.)
69
70 [HTML Underload specification]: https://cdn.rawgit.com/graue/esofiles/7ca16941/underload/underload.html
71 [The Esoteric File Archive]: https://esolangs.org/wiki/The_Esoteric_File_Archive
0 (:::::::):(:((^:()~((:)*~^)a~*^!!()~^))~*()~^^)~(^a(*~^)*a~*()~^!()~^)a~**^!!^S
0 (:(1)*(:(2)*(:(3)*(:(4)*(:(5)*(:(6)*(:(7)*(:(8)*(:(9)*(!~:^)))))))))):(
1 )!(~^~(~a~*~a~*)~a*^:(0)*)~a*~:(a(:^)*())~*a(:^)*~()~(0)((!^~)())(
2 )!((:(~:(,)*S~^!^)~a*^:^~!a~^*a*)~a*^:^):^
0 (Hello, world!)S
0 (12)S(*a(~:)~*^~):((1)S)~*~((2)S:*)~*:(~:()~)~*^(a(:^)*~a(*()~)~*^~^):^
0 (:aS(:^S^:)Sa:):^S^:(:aS(:^S^:)Sa:)
0 (:aSS):aSS
0 (a(:^)*S):^
0 (0)S((0)(1))(~:^:S*a~^~*a*~:^):^
2828 all: ${PROG}${EXE}
2929
3030 ${PROG}${EXE}: $(OBJS)
31 mkdir -p ../bin/
3231 $(CC) $(OBJS) -o ${PROG} $(LIBS)
3332
3433 stringie${O}: stringie.c
11 * stringie.c -- a brain-freezingly pedantic implementation of Underload in C
22 * (with all the limitations that that implies)
33 * Chris Pressey, September 2010
4 * Bug fix, August 2017: avoid memory overrun in (). Thanks to @stasoid for finding and suggesting fix.
4 * August 2017: bug fix to avoid memory overrun in (). Thanks to @stasoid for finding and suggesting fix.
5 * Summer 2018: own implementation of strdup to avoid warnings; ability to read from file; AUTOFLUSH; 1.0.
56 * This work is in the public domain.
67 */
78
1516 } *root;
1617
1718 void run(char *);
19
20 char *strdupe(const char *s)
21 {
22 char *t = malloc(strlen(s) + 1);
23 strcpy(t, s);
24 return t;
25 }
1826
1927 char *pop(void)
2028 {
4048 {
4149 char *e, *f;
4250 e = pop();
43 f = strdup(e);
51 f = strdupe(e);
4452 push(e);
4553 push(f);
4654 }
8997 char *e;
9098 e = pop();
9199 printf("%s", e);
100 #ifdef AUTOFLUSH
101 fflush(stdout);
102 #endif
92103 free(e);
93104 }
94105
164175 free(program);
165176 }
166177
178 char *readfile(FILE *f)
179 {
180 char chunk[256];
181 char *buffer;
182 int size = 256;
183 int len = 0;
184 int n;
185
186 buffer = malloc(size);
187
188 n = fread(chunk, 1, 256, f);
189 while (n > 0) {
190 if (len + n > size) {
191 size *= 2;
192 buffer = realloc(buffer, size);
193 }
194 memcpy(buffer + len, chunk, n);
195 len += n;
196 n = fread(chunk, 256, 1, f);
197 }
198
199 /* NUL-terminate the buffer; but first, make sure the NUL can fit! */
200 if (len + 1 > size) {
201 size *= 2;
202 buffer = realloc(buffer, size);
203 }
204 buffer[len + 1] = '\0';
205
206 return buffer;
207 }
208
167209 int main(int argc, char **argv)
168210 {
169 char *program = strdup(argv[1]);
211 char *program;
212 FILE *f;
213
214 if (argc >= 1) {
215 if (!strcmp(argv[1], "from") && argc >= 2) {
216 if ((f = fopen(argv[2], "r")) == NULL) {
217 exit(1);
218 }
219 program = readfile(f);
220 fclose(f);
221 } else {
222 program = strdupe(argv[1]);
223 }
224 }
170225 root = NULL;
171226 run(program);
172227 exit(0);