Mercurial > repo
comparison interps/befunge/bef.c @ 996:859f9b4339e6
<Gregor> tar xf egobot.tar.xz
author | HackBot |
---|---|
date | Sun, 09 Dec 2012 19:30:08 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
995:6883f5911eb7 | 996:859f9b4339e6 |
---|---|
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 } |