Initial import of bef-2.21 sources.
catseye
9 years ago
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 */ |