996
|
1 /* ******************************************************************
|
|
2
|
|
3 bef.c - The Original Befunge-93 Interpreter/Debugger in ANSI C
|
|
4 v2.21 Sep 20 2004 Chris Pressey, Cat's-Eye Technologies
|
|
5
|
|
6 Copyright (c)1993-2004, Cat's Eye Technologies.
|
|
7 All rights reserved.
|
|
8
|
|
9 Redistribution and use in source and binary forms, with or without
|
|
10 modification, are permitted provided that the following conditions
|
|
11 are met:
|
|
12
|
|
13 Redistributions of source code must retain the above copyright
|
|
14 notice, this list of conditions and the following disclaimer.
|
|
15
|
|
16 Redistributions in binary form must reproduce the above copyright
|
|
17 notice, this list of conditions and the following disclaimer in
|
|
18 the documentation and/or other materials provided with the
|
|
19 distribution.
|
|
20
|
|
21 Neither the name of Cat's Eye Technologies nor the names of its
|
|
22 contributors may be used to endorse or promote products derived
|
|
23 from this software without specific prior written permission.
|
|
24
|
|
25 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
|
|
26 CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
|
27 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
28 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
29 DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
|
|
30 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
|
31 OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
32 PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
|
33 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
34 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
35 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
36 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
37 POSSIBILITY OF SUCH DAMAGE.
|
|
38
|
|
39 ******************************************************************
|
|
40
|
|
41 Usage :
|
|
42
|
|
43 bef [-d] [-o] [-q] [-i] [-=]
|
|
44 [-r input-file] [-w output-file]
|
|
45 [-s stack-file] [-y delay] <befunge-source>
|
|
46
|
|
47 -d: visual ANSI debugging display
|
|
48 -o: do not fix off-by-one error (for old sources)
|
|
49 -q: produce no output except Befunge program output ('quiet')
|
|
50 -i: ignore unsupported instructions
|
|
51 -=: use b97-ish = directives
|
|
52 -r: redirect input from a specified file instead of stdin
|
|
53 -w: redirect output to a specified file instead of stdout
|
|
54 -s: write contents of stack to log file
|
|
55 -y: specify debugging delay in milliseconds
|
|
56
|
|
57 Compiles Under:
|
|
58
|
|
59 Borland C++ v3.1 (16-bit MS-DOS)
|
|
60 DJGPP v2.952 (32-bit Protected-Mode MS-DOS)
|
|
61 Mingw v2.
|
|
62
|
|
63 ******************************************************************
|
|
64
|
|
65 v2.21: Sep 2004, Chris Pressey
|
|
66 display correct version number
|
|
67 cleanup only, no functional changes
|
|
68
|
|
69 v2.20, Jul 2000, Chris Pressey
|
|
70 prettied up preprocessor directives a bit
|
|
71 added defines for Metroworks CodeWarrior
|
|
72 so that bef will build on MacOS
|
|
73 relicensed under BSD
|
|
74
|
|
75 v2.12, Mar 1998, Chris Pressey / compiles under Borland C++ v3.1
|
|
76 added -i and -= options. You must specify -= if
|
|
77 you want to use b97-esque directives or the Un*x-ish
|
|
78 # comment thing, or both.
|
|
79 automatically appends '.bf' to filenames containing no periods.
|
|
80 explicitly pops remaining stack elements at end of execution.
|
|
81 compatibility messages are displayed when quiet is not specified.
|
|
82 debug mode is much improved, especially I/O under BorlandC.
|
|
83 bounds checking on 'p' and 'g' instructions.
|
|
84
|
|
85 v2.11, Jan 1998, Chris Pressey / compiles under Borland C++ v3.1
|
|
86 divide by zero now produces the correct result
|
|
87 improved some minor aesthetic features (messages & debug)
|
|
88 ANSI is used only if not compiling under Borland C.
|
|
89
|
|
90 v2.10: Jul 1997, Chris Pressey
|
|
91 added -q command line option.
|
|
92 added primitive understanding of = directive from b97 spec.
|
|
93 any file with a =l directive but without =l b93 is rejected.
|
|
94 also understands # as a pre-directive line prefix for
|
|
95 Un*x-ish systems.
|
|
96
|
|
97 v2.02: Jun 1997, Chris Pressey
|
|
98 pads playfield with space characters. all unread
|
|
99 locations remain spaces.
|
|
100
|
|
101 v2.01: Jun 1997, Chris Pressey
|
|
102 command line switches are not case-insensitive.
|
|
103 fixes gcc Segmentation Fault error.
|
|
104
|
|
105 v2.00: Jun 1997, Chris Pressey
|
|
106 combines interpreter and debugger.
|
|
107 fixes ANSI error in debugger.
|
|
108 v1.02: Feb 1996, Chris Pressey
|
|
109 @ now pushes '@' onto the stack in stringmode instead of quitting.
|
|
110
|
|
111 v1.01: Feb 1996, Chris Pressey
|
|
112 fixes off-by-one error.
|
|
113
|
|
114 v1.00: Sept 1993, Chris Pressey
|
|
115 original Befunge-93 distribution.
|
|
116
|
|
117 ****************************************************************** */
|
|
118
|
|
119 /********************************************************* #PRAGMA'S */
|
|
120
|
|
121 /* This switches Borland C++ v3.1 to small memory model */
|
|
122 #ifdef __BORLANDC__
|
|
123 #pragma option -ms
|
|
124 #endif /* __BORLANDC__ */
|
|
125
|
|
126 /********************************************************* #INCLUDE'S */
|
|
127
|
|
128 #include <stdio.h>
|
|
129 #include <string.h>
|
|
130 #include <stdlib.h>
|
|
131 #include <ctype.h>
|
|
132 #include <time.h>
|
|
133 #ifdef __BORLANDC__
|
|
134 # include <dos.h>
|
|
135 # include <conio.h>
|
|
136 # define CONSOLE 1
|
|
137 # define CURSORSHAPE 1
|
|
138 #endif /* __BORLANDC__ */
|
|
139 #ifdef __MWERKS__
|
|
140 # include <console.h>
|
|
141 # define CONSOLE 1
|
|
142 #endif /* __MWERKS__ */
|
|
143
|
|
144 /********************************************************** #DEFINE'S */
|
|
145
|
|
146 #define LINEWIDTH 80
|
|
147 #define PAGEHEIGHT 25
|
|
148
|
|
149 #define SCREENWIDTH 79
|
|
150 #define SCREENHEIGHT 22
|
|
151
|
|
152 #define DEBUGROW 24
|
|
153 #define cur pg[y * LINEWIDTH + x]
|
|
154
|
|
155 /********************************************************* STRUCTURES */
|
|
156
|
|
157 struct stack /* stack structure, for values on stack */
|
|
158 {
|
|
159 signed long val;
|
|
160 struct stack *next;
|
|
161 } * head; /* head of stack */
|
|
162
|
|
163 /*************************************************** GLOBAL VARIABLES */
|
|
164
|
|
165 char pg[LINEWIDTH * PAGEHEIGHT]; /* befunge 'page' of source */
|
|
166 int x = 0, y = 0; /* x and y of the PC */
|
|
167 int dx = 1, dy = 0; /* direction of the PC */
|
|
168 int debug = 0; /* flag : display ANSI debugging? */
|
|
169 int infile = 0, ia; /* flag : use input file, and assoc arg? */
|
|
170 int outfile = 0, oa; /* flag : use output file, and assoc arg? */
|
|
171 int stackfile = 0, sa; /* flag : use stack log file, & assoc arg? */
|
|
172 int stringmode = 0; /* flag : are we in string mode? */
|
|
173 int quiet = 0; /* flag : are we quiet? */
|
|
174 int v10err_compat = 0; /* flag : emulate v1.0 off-by-one err? */
|
|
175 int deldur = 25; /* debugging delay in milliseconds */
|
|
176 int ignore_unsupported = 0; /* flag : ignore unsupported instructions? */
|
|
177 int use_b97directives = 0; /* flag : use b97-esque directives? */
|
|
178
|
|
179 /********************************************************* PROTOTYPES */
|
|
180
|
|
181 void push (signed long val);
|
|
182 signed long pop (void);
|
|
183
|
|
184 /******************************************************* MAIN PROGRAM */
|
|
185
|
|
186 int main (argc, argv)
|
|
187 int argc;
|
|
188 char **argv;
|
|
189 {
|
|
190 FILE *f=NULL;
|
|
191 FILE *fi=NULL;
|
|
192 FILE *fo=NULL;
|
|
193 FILE *fs=NULL;
|
|
194 int i;
|
|
195 char filename[128];
|
|
196
|
|
197 #ifdef __MWERKS__
|
|
198 argc = ccommand(&argv);
|
|
199 #endif /* __MWERKS__ */
|
|
200
|
|
201 srand((unsigned)time(0));
|
|
202
|
|
203 if (argc < 2)
|
|
204 {
|
|
205 printf ("USAGE: bef [-d] [-o] [-q] [-i] [-=]\n");
|
|
206 printf (" [-r input] [-w output] [-s stack] [-y delay] foo.bf\n");
|
|
207 exit (0);
|
|
208 }
|
|
209 for (i = 1; i < argc; i++)
|
|
210 {
|
|
211 if (!strcmp(argv[i], "-o")) { v10err_compat = 1; }
|
|
212 if (!strcmp(argv[i], "-d")) { debug = 1; }
|
|
213 if (!strcmp(argv[i], "-r")) { infile = 1; ia = i + 1; }
|
|
214 if (!strcmp(argv[i], "-w")) { outfile = 1; oa = i + 1; }
|
|
215 if (!strcmp(argv[i], "-s")) { stackfile = 1; sa = i + 1; }
|
|
216 if (!strcmp(argv[i], "-y")) { deldur = atoi(argv[i + 1]); }
|
|
217 if (!strcmp(argv[i], "-q")) { quiet = 1; }
|
|
218 if (!strcmp(argv[i], "-i")) { ignore_unsupported = 1; }
|
|
219 if (!strcmp(argv[i], "-=")) { use_b97directives = 1; }
|
|
220 }
|
|
221 if (!quiet)
|
|
222 {
|
|
223 //printf ("Befunge-93 Interpreter/Debugger v2.21\n");
|
|
224 }
|
|
225
|
|
226 memset(pg, ' ', LINEWIDTH * PAGEHEIGHT);
|
|
227
|
|
228 strcpy(filename, argv[argc - 1]);
|
|
229 if (strchr(filename, '.') == NULL)
|
|
230 {
|
|
231 strcat(filename, ".bf");
|
|
232 }
|
|
233
|
|
234 if ((f = fopen (filename, "r")) != NULL) /*** Input Phase */
|
|
235 {
|
|
236 int x = 0, y = 0;
|
|
237 char dc = '=', tc = ' ';
|
|
238 int tt = 0; char s[80];
|
|
239 int accept_pound = 1;
|
|
240
|
|
241 while (!feof (f))
|
|
242 {
|
|
243 cur = fgetc (f);
|
|
244 if (use_b97directives && (x == 0) && ((cur == dc) || ((accept_pound) && (cur == '#'))))
|
|
245 {
|
|
246 if (cur != '#') accept_pound = 0;
|
|
247 tc = fgetc (f);
|
|
248 if (tc == 'l')
|
|
249 {
|
|
250 while (tc != ' ')
|
|
251 {
|
|
252 tc = fgetc (f);
|
|
253 }
|
|
254 while (tc != '\n')
|
|
255 {
|
|
256 tc = fgetc (f);
|
|
257 if (tc != '\n') { s[tt++] = tc; s[tt] = (char)0; }
|
|
258 }
|
|
259 if (strcmp(s, "b93"))
|
|
260 {
|
|
261 fprintf(stderr, "Error: only Befunge-93 (not %s) sources are supported by BEF.\n", s);
|
|
262 exit(10);
|
|
263 }
|
|
264 }
|
|
265 while (tc != '\n')
|
|
266 {
|
|
267 tc = fgetc (f);
|
|
268 }
|
|
269 } else
|
|
270 {
|
|
271 accept_pound = 0;
|
|
272 if (cur == '\n')
|
|
273 {
|
|
274 cur = ' ';
|
|
275 x = 0;
|
|
276 y++;
|
|
277 if (y >= PAGEHEIGHT) break;
|
|
278 } else
|
|
279 {
|
|
280 x++;
|
|
281 if (x >= LINEWIDTH)
|
|
282 {
|
|
283 x = 0;
|
|
284 y++;
|
|
285 if (y >= PAGEHEIGHT) break;
|
|
286 }
|
|
287 }
|
|
288 }
|
|
289 }
|
|
290 fclose (f);
|
|
291 } else
|
|
292 {
|
|
293 printf ("Error: couldn't open '%s' for input.\n", filename);
|
|
294 exit (0);
|
|
295 }
|
|
296
|
|
297 if (infile)
|
|
298 {
|
|
299 if (!(fi = fopen (argv[ia], "r")))
|
|
300 {
|
|
301 printf ("Error : couldn't open '%s' for input.\n", argv[ia]);
|
|
302 exit (0);
|
|
303 }
|
|
304 }
|
|
305
|
|
306 if (outfile)
|
|
307 {
|
|
308 if (!(fo = fopen (argv[oa], "w")))
|
|
309 {
|
|
310 printf ("Error : couldn't open '%s' for output.\n", argv[oa]);
|
|
311 exit (0);
|
|
312 }
|
|
313 }
|
|
314
|
|
315 if (stackfile)
|
|
316 {
|
|
317 if (!(fs = fopen (argv[sa], "w")))
|
|
318 {
|
|
319 printf ("Error : couldn't open '%s' for output.\n", argv[sa]);
|
|
320 exit (0);
|
|
321 }
|
|
322 }
|
|
323
|
|
324 if (debug)
|
|
325 {
|
|
326
|
|
327 #ifdef CONSOLE
|
|
328 clrscr();
|
|
329 # ifdef CURSORSHAPE
|
|
330 _setcursortype(_NOCURSOR);
|
|
331 # endif /* CURSORSHAPE */
|
|
332 #else
|
|
333 printf ("%c[1;1H", 27);
|
|
334 printf ("%c[2J", 27);
|
|
335 #endif /* CONSOLE */
|
|
336
|
|
337 for(y = 0; y < SCREENHEIGHT; y++)
|
|
338 {
|
|
339 for(x = 0; x < SCREENWIDTH; x++)
|
|
340 {
|
|
341 if (isprint(cur))
|
|
342 {
|
|
343 printf("%c", cur);
|
|
344 }
|
|
345 }
|
|
346 printf("\n");
|
|
347 }
|
|
348
|
|
349 x = y = 0;
|
|
350
|
|
351 #ifdef CUSRORSHAPE
|
|
352 _setcursortype(_SOLIDCURSOR);
|
|
353 #endif /* CUSRORSHAPE */
|
|
354
|
|
355 }
|
|
356
|
|
357 while ((cur != '@') || (stringmode)) /*** Intepreting Phase */
|
|
358 {
|
|
359 if (debug)
|
|
360 {
|
|
361 if ((y < SCREENHEIGHT) && (x < SCREENWIDTH))
|
|
362 {
|
|
363 #ifdef CONSOLE
|
|
364 gotoxy(x+1, y+1);
|
|
365 if (kbhit())
|
|
366 {
|
|
367 char c;
|
|
368 /* ideally, pop up a debugging tool. for now, exit. */
|
|
369 c = getch();
|
|
370 if (c == 0)
|
|
371 {
|
|
372 c = getch();
|
|
373 } else
|
|
374 {
|
|
375 if (c == 27)
|
|
376 {
|
|
377 /* pause */
|
|
378 c = getch();
|
|
379 if (c == 0)
|
|
380 {
|
|
381 c = getch();
|
|
382 } else
|
|
383 {
|
|
384 if (c == 27)
|
|
385 {
|
|
386 goto the_end;
|
|
387 }
|
|
388 }
|
|
389 }
|
|
390 }
|
|
391 }
|
|
392 #else
|
|
393 printf ("%c[%d;%dH", 27, y+1, x+1);
|
|
394 fflush (stdout);
|
|
395 #endif /* CONSOLE */
|
|
396 }
|
|
397 #if __BORLANDC__
|
|
398 delay (deldur);
|
|
399 #endif /* __BORLANDC __ */
|
|
400 }
|
|
401 if (stringmode && (cur != '"'))
|
|
402 push (cur);
|
|
403 else if (isdigit (cur))
|
|
404 push (cur - '0');
|
|
405 else
|
|
406 switch (cur)
|
|
407 {
|
|
408 case '>': /* PC Right */
|
|
409 dx = 1;
|
|
410 dy = 0;
|
|
411 break;
|
|
412 case '<': /* PC Left */
|
|
413 dx = -1;
|
|
414 dy = 0;
|
|
415 break;
|
|
416 case '^': /* PC Up */
|
|
417 dx = 0;
|
|
418 dy = -1;
|
|
419 break;
|
|
420 case 'v': /* PC Down */
|
|
421 dx = 0;
|
|
422 dy = 1;
|
|
423 break;
|
|
424 case '|': /* Vertical 'If' */
|
|
425 dx = 0;
|
|
426 if (pop ())
|
|
427 dy = -1;
|
|
428 else
|
|
429 dy = 1;
|
|
430 break;
|
|
431 case '_': /* Horizontal 'If' */
|
|
432 dy = 0;
|
|
433 if (pop ())
|
|
434 dx = -1;
|
|
435 else
|
|
436 dx = 1;
|
|
437 break;
|
|
438 case '+': /* Add */
|
|
439 push (pop () + pop ());
|
|
440 break;
|
|
441 case '-': /* Subtract */
|
|
442 {
|
|
443 long a = pop();
|
|
444 long b = pop();
|
|
445 push(b - a);
|
|
446 }
|
|
447 break;
|
|
448 case '*': /* Multiply */
|
|
449 push (pop () * pop ());
|
|
450 break;
|
|
451 case '/': /* Integer Divide */
|
|
452 {
|
|
453 signed long a = pop ();
|
|
454 signed long b = pop ();
|
|
455 if (a == 0)
|
|
456 {
|
|
457 if (!outfile)
|
|
458 {
|
|
459 printf("What do you want %ld/0 to be? ", b);
|
|
460 } else
|
|
461 {
|
|
462 fprintf(fo, "What do you want %ld/0 to be? ", b);
|
|
463 }
|
|
464 if (infile)
|
|
465 {
|
|
466 fscanf (fi, "%ld", &b);
|
|
467 push (b);
|
|
468 } else
|
|
469 {
|
|
470 if (!debug)
|
|
471 {
|
|
472 fscanf (stdin, "%ld", &b);
|
|
473 push (b);
|
|
474 }
|
|
475 }
|
|
476 } else
|
|
477 {
|
|
478 push (b / a);
|
|
479 }
|
|
480 }
|
|
481 break;
|
|
482 case '%': /* Modulo */
|
|
483 {
|
|
484 signed long a = pop ();
|
|
485 signed long b = pop ();
|
|
486 push (b % a);
|
|
487 }
|
|
488 break;
|
|
489 case '\\': /* Swap */
|
|
490 {
|
|
491 signed long a = pop ();
|
|
492 signed long b = pop ();
|
|
493 push (a);
|
|
494 push (b);
|
|
495 }
|
|
496 break;
|
|
497 case '.': /* Pop Out Integer */
|
|
498 {
|
|
499 if (outfile)
|
|
500 {
|
|
501 fprintf (fo, "%ld ", pop ());
|
|
502 fflush (fo);
|
|
503 } else
|
|
504 {
|
|
505 if (!debug)
|
|
506 {
|
|
507 fprintf (stdout, "%ld ", pop ());
|
|
508 fflush (stdout);
|
|
509 } else
|
|
510 {
|
|
511 #ifdef CONSOLE
|
|
512 int x, y;
|
|
513 char s[172], t[172];
|
|
514 x = wherex();
|
|
515 y = wherey();
|
|
516 sprintf(s, "%ld ", pop());
|
|
517 gettext(1+strlen(s), DEBUGROW, 80, DEBUGROW, t);
|
|
518 puttext(1, DEBUGROW, 80-strlen(s), DEBUGROW, t);
|
|
519 gotoxy(81-strlen(s), DEBUGROW);
|
|
520 cputs(s);
|
|
521 gotoxy(x, y);
|
|
522 #endif /* CONSOLE */
|
|
523 }
|
|
524 }
|
|
525 }
|
|
526 break;
|
|
527 case ',': /* Pop Out ASCII */
|
|
528 {
|
|
529 if (outfile)
|
|
530 {
|
|
531 fprintf (fo, "%c", (char)pop ());
|
|
532 fflush (fo);
|
|
533 } else
|
|
534 {
|
|
535 if (!debug)
|
|
536 {
|
|
537 fprintf (stdout, "%c", (char)pop ());
|
|
538 fflush (stdout);
|
|
539 } else
|
|
540 {
|
|
541 #ifdef CONSOLE
|
|
542 int x, y;
|
|
543 long int p = pop();
|
|
544 char t[172];
|
|
545 x = wherex();
|
|
546 y = wherey();
|
|
547 gettext(2, DEBUGROW, 80, DEBUGROW, t);
|
|
548 puttext(1, DEBUGROW, 79, DEBUGROW, t);
|
|
549 gotoxy(80, DEBUGROW);
|
|
550 if ((p >= 32) && (p <= 255))
|
|
551 {
|
|
552 putch((int)p);
|
|
553 } else
|
|
554 {
|
|
555 if (p == 10)
|
|
556 {
|
|
557 putch(179);
|
|
558 } else
|
|
559 {
|
|
560 putch(168);
|
|
561 }
|
|
562 }
|
|
563 gotoxy(x, y);
|
|
564 #endif /* CONSOLE */
|
|
565 }
|
|
566 }
|
|
567 }
|
|
568 break;
|
|
569 case '"': /* Toggle String Mode */
|
|
570 stringmode = !stringmode;
|
|
571 break;
|
|
572 case ':': /* Duplicate */
|
|
573 {
|
|
574 signed long a = pop ();
|
|
575 push (a);
|
|
576 push (a);
|
|
577 }
|
|
578 break;
|
|
579 case '!': /* Negate */
|
|
580 if (pop())
|
|
581 push(0);
|
|
582 else
|
|
583 push(1);
|
|
584 break;
|
|
585 case '`':
|
|
586 {
|
|
587 signed long b = pop ();
|
|
588 signed long a = pop ();
|
|
589 push (a > b);
|
|
590 }
|
|
591 break;
|
|
592 case '#': /* Bridge */
|
|
593 x += dx;
|
|
594 y += dy;
|
|
595 break;
|
|
596 case '$': /* Pop and Discard */
|
|
597 pop ();
|
|
598 break;
|
|
599 case '?': /* Random Redirect */
|
|
600 switch ((rand () / 32) % 4)
|
|
601 {
|
|
602 case 0:
|
|
603 dx = 1;
|
|
604 dy = 0;
|
|
605 break;
|
|
606 case 1:
|
|
607 dx = -1;
|
|
608 dy = 0;
|
|
609 break;
|
|
610 case 2:
|
|
611 dx = 0;
|
|
612 dy = -1;
|
|
613 break;
|
|
614 case 3:
|
|
615 dx = 0;
|
|
616 dy = 1;
|
|
617 break;
|
|
618 }
|
|
619 break;
|
|
620 case '&': /* Input Integer */
|
|
621 {
|
|
622 signed long b;
|
|
623 if (infile)
|
|
624 {
|
|
625 fscanf (fi, "%ld", &b);
|
|
626 push (b);
|
|
627 } else
|
|
628 {
|
|
629 if (!debug)
|
|
630 {
|
|
631 fscanf (stdin, "%ld", &b);
|
|
632 push (b);
|
|
633 } else
|
|
634 {
|
|
635 #ifdef CONSOLE
|
|
636 int x, y;
|
|
637 long int p;
|
|
638 char t[172];
|
|
639 x = wherex();
|
|
640 y = wherey();
|
|
641 gettext(10, DEBUGROW, 80, DEBUGROW, t);
|
|
642 puttext(1, DEBUGROW, 71, DEBUGROW, t);
|
|
643 gotoxy(72, DEBUGROW);
|
|
644 clreol();
|
|
645 cscanf("%ld", &p);
|
|
646 push(p);
|
|
647 gotoxy(x, y);
|
|
648 #endif /* CONSOLE */
|
|
649 }
|
|
650 }
|
|
651 }
|
|
652 break;
|
|
653 case '~': /* Input ASCII */
|
|
654 {
|
|
655 char c;
|
|
656 if (infile)
|
|
657 {
|
|
658 c = fgetc (fi);
|
|
659 push (c);
|
|
660 } else
|
|
661 {
|
|
662 if (!debug)
|
|
663 {
|
|
664 c = fgetc (stdin);
|
|
665 push (c);
|
|
666 } else
|
|
667 {
|
|
668 #ifdef CONSOLE
|
|
669 int x, y;
|
|
670 long int p;
|
|
671 char t[172];
|
|
672 x = wherex();
|
|
673 y = wherey();
|
|
674 gettext(2, DEBUGROW, 80, DEBUGROW, t);
|
|
675 puttext(1, DEBUGROW, 79, DEBUGROW, t);
|
|
676 gotoxy(80, DEBUGROW);
|
|
677 clreol();
|
|
678 p = getche();
|
|
679 if (p == '\r')
|
|
680 {
|
|
681 p = '\n';
|
|
682 gotoxy(80, DEBUGROW);
|
|
683 putch(179);
|
|
684 }
|
|
685 push(p);
|
|
686 gotoxy(x, y);
|
|
687 #endif /* CONSOLE */
|
|
688 }
|
|
689 }
|
|
690 }
|
|
691 break;
|
|
692 case 'g': /* Get Value */
|
|
693 {
|
|
694 signed long y = pop (), x = pop ();
|
|
695 if ((y < PAGEHEIGHT) && (y >= 0) && (x < LINEWIDTH) && (x >= 0))
|
|
696 {
|
|
697 push (cur);
|
|
698 } else
|
|
699 {
|
|
700 if (!debug)
|
|
701 {
|
|
702 if (!quiet)
|
|
703 {
|
|
704 fprintf(stderr, "g 'Get' instruction out of bounds (%ld,%ld)\n", x, y);
|
|
705 }
|
|
706 }
|
|
707 push (0);
|
|
708 }
|
|
709 }
|
|
710 break;
|
|
711 case 'p': /* Put Value */
|
|
712 {
|
|
713 signed long y = pop (), x = pop ();
|
|
714 if ((y < PAGEHEIGHT) && (y >= 0) && (x < LINEWIDTH) && (x >= 0))
|
|
715 {
|
|
716 cur = pop ();
|
|
717 } else
|
|
718 {
|
|
719 if (!debug)
|
|
720 {
|
|
721 if (!quiet)
|
|
722 {
|
|
723 fprintf(stderr, "p 'Put' instruction out of bounds (%ld,%ld)\n", x, y);
|
|
724 }
|
|
725 }
|
|
726 pop();
|
|
727 }
|
|
728 if ((debug) && (y < SCREENHEIGHT) && (x < SCREENWIDTH))
|
|
729 {
|
|
730 #ifdef CONSOLE
|
|
731 gotoxy(x+1,y+1);
|
|
732 #else
|
|
733 printf ("%c[%d;%dH", 27, (int)(y+1), (int)(x+1));
|
|
734 #endif /* CONSOLE */
|
|
735 if (isprint (cur)) printf ("%c", cur); else printf(".");
|
|
736 }
|
|
737 }
|
|
738 break;
|
|
739 case ' ':
|
|
740 break;
|
|
741 default:
|
|
742 if ((!debug) && (!ignore_unsupported) && (!quiet))
|
|
743 {
|
|
744 fprintf(stderr, "Unsupported instruction '%c' (0x%02x) (maybe not Befunge-93?)\n", cur, cur);
|
|
745 }
|
|
746 break;
|
|
747 }
|
|
748 x += dx;
|
|
749 y += dy;
|
|
750 if (x < 0)
|
|
751 if (v10err_compat)
|
|
752 {
|
|
753 x = LINEWIDTH;
|
|
754 } else
|
|
755 {
|
|
756 x = LINEWIDTH - 1;
|
|
757 }
|
|
758 else
|
|
759 x = x % LINEWIDTH;
|
|
760 if (y < 0)
|
|
761 if (v10err_compat)
|
|
762 {
|
|
763 y = PAGEHEIGHT;
|
|
764 } else
|
|
765 {
|
|
766 y = PAGEHEIGHT - 1;
|
|
767 }
|
|
768 else
|
|
769 y = y % PAGEHEIGHT;
|
|
770 if (stackfile)
|
|
771 {
|
|
772 struct stack *s;
|
|
773 for (s = head; s; s = s->next)
|
|
774 fprintf(fs, "%ld ", s->val);
|
|
775 fprintf(fs, "\n");
|
|
776 fflush(fs);
|
|
777 }
|
|
778 }
|
|
779
|
|
780 #ifdef CONSOLE
|
|
781 the_end:
|
|
782 #endif /* CONSOLE */
|
|
783
|
|
784 while (head != NULL) { pop(); }
|
|
785 if (fi != NULL) fclose (fi);
|
|
786 if (fo != NULL) fclose (fo);
|
|
787 if (fs != NULL) fclose (fs);
|
|
788
|
|
789 if (debug)
|
|
790 {
|
|
791 #ifdef CONSOLE
|
|
792 # ifdef CURSORSHAPE
|
|
793 _setcursortype(_NORMALCURSOR);
|
|
794 # endif /* CURSORSHAPE */
|
|
795 gotoxy(1,22);
|
|
796 #else
|
|
797 printf ("%c[22;1H", 27);
|
|
798 #endif /* CONSOLE */
|
|
799 }
|
|
800
|
|
801 exit (0);
|
|
802 return 0;
|
|
803 }
|
|
804
|
|
805 /*
|
|
806 * pushes a value onto the stack.
|
|
807 */
|
|
808 void push (val)
|
|
809 signed long val;
|
|
810 {
|
|
811 struct stack *s;
|
|
812 s = (struct stack *) malloc (sizeof (struct stack));
|
|
813 s->val = val;
|
|
814 s->next = head;
|
|
815 head = s;
|
|
816 }
|
|
817
|
|
818 /*
|
|
819 * pops a value off the stack. returns 0 in case of underflow.
|
|
820 */
|
|
821 signed long pop ()
|
|
822 {
|
|
823 signed long v;
|
|
824 struct stack *s = head;
|
|
825 if (s)
|
|
826 {
|
|
827 v = head->val;
|
|
828 head = head->next;
|
|
829 free (s);
|
|
830 return v;
|
|
831 } else
|
|
832 {
|
|
833 return 0;
|
|
834 }
|
|
835 }
|