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