0 | 0 |
/********************************************************************
|
1 | 1 |
|
2 | 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 | |
|
5 | |
Copyright (c)1997-2012, Chris Pressey, Cat's Eye Technologies.
|
|
3 |
|
|
4 |
Copyright (c)1997-2018, Chris Pressey, Cat's Eye Technologies.
|
6 | 5 |
All rights reserved.
|
7 | 6 |
|
8 | 7 |
Redistribution and use in source and binary forms, with or without
|
|
38 | 37 |
|
39 | 38 |
Usage :
|
40 | 39 |
|
41 | |
bef2c [-p] [-o] [-w width] [-h height] <befunge-source> <c-destination>
|
42 | |
|
43 | |
-p : suppress pre-optimization
|
44 | |
-o : suppress post-optimization
|
|
40 |
bef2c [-O] [-w width] [-h height] <befunge-source> <c-destination>
|
|
41 |
|
|
42 |
-O : enable [buggy] post-optimization phase
|
45 | 43 |
-w : explicit width
|
46 | 44 |
-h : explicit height
|
47 | 45 |
|
48 | 46 |
Known to Compile Under :
|
49 | 47 |
|
50 | 48 |
Borland C++ v3.1 (DOS)
|
|
49 |
gcc 5.4.0 (Ubuntu 16.04)
|
51 | 50 |
|
52 | 51 |
History:
|
|
52 |
|
|
53 |
v1.0: circa Jun 2018
|
|
54 |
fixes submitted by https://github.com/serprex (thanks!):
|
|
55 |
- avoid double free due to double fclose
|
|
56 |
- handle trampoline at leftmost/topmost edges
|
|
57 |
- don't load NULs into playfield
|
|
58 |
- use %% instead of %c with '%' being passed in
|
|
59 |
- avoid freeing fo/fi on failure to open
|
|
60 |
removed -p flag as it is equivalent to
|
|
61 |
`-w 80 -h 25`, just use that instead
|
|
62 |
replaced -o (disable post-optimization) flag
|
|
63 |
with -O (enable post-optimization) because buggy
|
|
64 |
show usage and exit if unrecognized command-line
|
|
65 |
options are given
|
|
66 |
exit with a non-zero exit code if an error occurs
|
|
67 |
when detecing pageheight, add one on the assumption
|
|
68 |
that the source does not end with a newline
|
|
69 |
(this lets some existing example programs compile)
|
53 | 70 |
|
54 | 71 |
v0.94: Sep 2004, Chris Pressey
|
55 | 72 |
display correct version number
|
|
79 | 96 |
int pageheight = 1; /* 25 */
|
80 | 97 |
|
81 | 98 |
#define cur pg[y * 80 + x]
|
82 | |
#define shrink(s) s[strlen(s)-1]=0
|
83 | 99 |
|
84 | 100 |
#define RIGHT "_%2.2d_%2.2d_R"
|
85 | 101 |
#define LEFT "_%2.2d_%2.2d_L"
|
|
92 | 108 |
#define x_left (x ? x-1 : linewidth-1)
|
93 | 109 |
|
94 | 110 |
#define y_2down (y+2)%pageheight
|
95 | |
#define y_2up ((y>1) ? y-2 : ((pageheight-2)<0 ? 0 : (pageheight-2)))
|
|
111 |
#define y_2up ((y>1) ? y-2 : ((pageheight-2)<0 ? 0 : (y-2+pageheight)))
|
96 | 112 |
#define x_2right (x+2)%linewidth
|
97 | |
#define x_2left ((x>1) ? x-2 : ((linewidth-2)<0 ? 0 : (linewidth-2)))
|
|
113 |
#define x_2left ((x>1) ? x-2 : ((linewidth-2)<0 ? 0 : (x-2+linewidth)))
|
98 | 114 |
|
99 | 115 |
#define ALL RIGHT ": " LEFT ": " UP ": " DOWN ":\n"
|
100 | 116 |
|
|
108 | 124 |
char in[255];
|
109 | 125 |
char pg[2000]; /* befunge 'page' of source */
|
110 | 126 |
int x = 0, y = 0, d = 0; /* loopers */
|
111 | |
int pre_optimize = 1; /* flag: optimize before compile? */
|
112 | |
int post_optimize = 1; /* flag: optimize after compile? */
|
|
127 |
int post_optimize = 0; /* flag: optimize after compile? */
|
113 | 128 |
|
114 | 129 |
int labelrefs[8000]; /* postoptimization table */
|
115 | 130 |
char s[255];
|
|
117 | 132 |
|
118 | 133 |
/********************************************************* PROTOTYPES */
|
119 | 134 |
|
|
135 |
void usage(char *);
|
120 | 136 |
int main (int, char **);
|
|
137 |
|
|
138 |
/********************************************************** FUNCTIONS */
|
|
139 |
|
|
140 |
void usage(char *e)
|
|
141 |
{
|
|
142 |
printf ("USAGE : %s [-O] [-w width] [-h height] <befunge-source> <c-destination>\n", e);
|
|
143 |
exit (1);
|
|
144 |
}
|
121 | 145 |
|
122 | 146 |
/******************************************************* MAIN PROGRAM */
|
123 | 147 |
|
|
136 | 160 |
|
137 | 161 |
srand (time (0));
|
138 | 162 |
|
139 | |
printf ("Befunge-93 to ANSI C Compiler v0.94\n");
|
140 | |
|
141 | |
if (argc < 3)
|
142 | |
{
|
143 | |
printf ("USAGE : %s [-p] [-o] [-w width] [-h height] <befunge-source> <c-destination>\n", argv[0]);
|
144 | |
exit (0);
|
145 | |
}
|
|
163 |
printf ("Befunge-93 to ANSI C Compiler v1.0\n");
|
|
164 |
|
|
165 |
if (argc < 3) usage(argv[0]);
|
146 | 166 |
for (i = 1; i < argc; i++)
|
147 | 167 |
{
|
148 | |
if (!strcmp(argv[i], "-p")) { pre_optimize = 0; linewidth=80; pageheight=25; }
|
149 | |
if (!strcmp(argv[i], "-o")) { post_optimize = 0; }
|
150 | |
if (!strcmp(argv[i], "-w")) { linewidth = atoi(argv[i+1]); }
|
151 | |
if (!strcmp(argv[i], "-h")) { pageheight = atoi(argv[i+1]); }
|
|
168 |
if (argv[i][0] == '-')
|
|
169 |
{
|
|
170 |
if (!strcmp(argv[i], "-O")) { post_optimize = 1; }
|
|
171 |
else if (!strcmp(argv[i], "-w")) { linewidth = atoi(argv[i+1]); }
|
|
172 |
else if (!strcmp(argv[i], "-h")) { pageheight = atoi(argv[i+1]); }
|
|
173 |
else usage(argv[0]);
|
|
174 |
}
|
152 | 175 |
}
|
153 | 176 |
if ((fi = fopen (argv[argc - 2], "r")) != NULL) /*** Input Phase */
|
154 | 177 |
{
|
155 | 178 |
int x = 0, y = 0;
|
156 | 179 |
while (!feof (fi))
|
157 | 180 |
{
|
158 | |
cur = fgetc (fi);
|
159 | |
if ((x+1)>linewidth) linewidth=x+1;
|
160 | |
if ((y+1)>pageheight) pageheight=y+1;
|
161 | |
if (cur == '\n')
|
162 | |
{
|
163 | |
cur = ' ';
|
|
181 |
int ch = fgetc (fi);
|
|
182 |
if (ch == -1) break;
|
|
183 |
if (ch == '\n')
|
|
184 |
{
|
164 | 185 |
x = 0;
|
165 | 186 |
y++;
|
166 | 187 |
if (y >= 25) break;
|
|
188 |
else if (y > pageheight) pageheight=y;
|
167 | 189 |
} else
|
168 | 190 |
{
|
|
191 |
cur = ch;
|
169 | 192 |
x++;
|
170 | 193 |
if (x >= 80)
|
171 | 194 |
{
|
172 | 195 |
x = 0;
|
173 | 196 |
y++;
|
174 | 197 |
if (y >= 25) break;
|
|
198 |
else if (y > pageheight) pageheight=y;
|
|
199 |
} else if (x > linewidth)
|
|
200 |
{
|
|
201 |
linewidth = x;
|
175 | 202 |
}
|
176 | 203 |
}
|
177 | 204 |
}
|
178 | |
fclose (fi);
|
179 | 205 |
} else
|
180 | 206 |
{
|
181 | 207 |
printf ("Error : couldn't open '%s' for input.\n", argv[argc - 1]);
|
182 | |
exit (0);
|
183 | |
}
|
|
208 |
exit (1);
|
|
209 |
}
|
|
210 |
|
|
211 |
/* Most Befunge-93 sources do not end with a newline. Therefore: */
|
|
212 |
if (pageheight < 25) pageheight++;
|
184 | 213 |
|
185 | 214 |
if (!(fo = fopen (argv[argc - 1], "w"))) /*** Output */
|
186 | 215 |
{
|
187 | 216 |
printf ("Error : couldn't open '%s' for output.\n", argv[argc - 1]);
|
188 | |
exit (0);
|
189 | |
}
|
190 | |
|
|
217 |
exit (1);
|
|
218 |
}
|
|
219 |
|
|
220 |
printf ("Loaded %d columns by %d rows.\n", linewidth, pageheight);
|
191 | 221 |
printf ("Compiling");
|
192 | 222 |
|
193 | 223 |
fprintf (fo, "/* %s converted to ANSI C from %s by bef2c */\n",
|
|
208 | 238 |
{
|
209 | 239 |
for(x = 0; x < linewidth; x++)
|
210 | 240 |
{
|
211 | |
if (cur!='\\')
|
212 | |
{
|
213 | |
fprintf (fo, " pg[%d]='%c';\n", y * 80 + x, cur);
|
214 | |
} else
|
215 | |
{
|
216 | |
fprintf (fo, " pg[%d]='%c%c';\n", y * 80 + x, cur, cur);
|
217 | |
}
|
|
241 |
if (cur) fprintf (fo, " pg[%d]=%d;\n", y * 80 + x, cur);
|
218 | 242 |
}
|
219 | 243 |
}
|
220 | 244 |
|
|
270 | 294 |
ECHO("a=pop();b=pop();push(b/a);");
|
271 | 295 |
break;
|
272 | 296 |
case '%':
|
273 | |
sprintf(t, "a=pop();b=pop();push(b%ca);", '%');
|
|
297 |
sprintf(t, "a=pop();b=pop();push(b%%a);");
|
274 | 298 |
fprintf(fo, RIGHT ": %s goto " RIGHT ";\n", x, y, t, x_right, y);
|
275 | 299 |
fprintf(fo, LEFT ": %s goto " LEFT ";\n", x, y, t, x_left, y);
|
276 | 300 |
fprintf(fo, UP ": %s goto " UP ";\n", x, y, t, x, y_up);
|
|
283 | 307 |
ECHO("a=pop();push(a);push(a);");
|
284 | 308 |
break;
|
285 | 309 |
case '.':
|
286 | |
fprintf(fo, RIGHT ": fprintf(stdout,\"%cld \",pop());fflush(stdout); goto " RIGHT ";\n", x, y, '%', x_right, y);
|
287 | |
fprintf(fo, LEFT ": fprintf(stdout,\"%cld \",pop());fflush(stdout); goto " LEFT ";\n", x, y, '%', x_left, y);
|
288 | |
fprintf(fo, UP ": fprintf(stdout,\"%cld \",pop());fflush(stdout); goto " UP ";\n", x, y, '%', x, y_up);
|
289 | |
fprintf(fo, DOWN ": fprintf(stdout,\"%cld \",pop());fflush(stdout); goto " DOWN ";\n", x, y, '%', x, y_down);
|
|
310 |
fprintf(fo, RIGHT ": fprintf(stdout,\"%%ld \",pop());fflush(stdout); goto " RIGHT ";\n", x, y, x_right, y);
|
|
311 |
fprintf(fo, LEFT ": fprintf(stdout,\"%%ld \",pop());fflush(stdout); goto " LEFT ";\n", x, y, x_left, y);
|
|
312 |
fprintf(fo, UP ": fprintf(stdout,\"%%ld \",pop());fflush(stdout); goto " UP ";\n", x, y, x, y_up);
|
|
313 |
fprintf(fo, DOWN ": fprintf(stdout,\"%%ld \",pop());fflush(stdout); goto " DOWN ";\n", x, y, x, y_down);
|
290 | 314 |
break;
|
291 | 315 |
case ',':
|
292 | |
fprintf(fo, RIGHT ": fprintf(stdout,\"%cc\",pop());fflush(stdout); goto " RIGHT ";\n", x, y, '%', x_right, y);
|
293 | |
fprintf(fo, LEFT ": fprintf(stdout,\"%cc\",pop());fflush(stdout); goto " LEFT ";\n", x, y, '%', x_left, y);
|
294 | |
fprintf(fo, UP ": fprintf(stdout,\"%cc\",pop());fflush(stdout); goto " UP ";\n", x, y, '%', x, y_up);
|
295 | |
fprintf(fo, DOWN ": fprintf(stdout,\"%cc\",pop());fflush(stdout); goto " DOWN ";\n", x, y, '%', x, y_down);
|
|
316 |
fprintf(fo, RIGHT ": fprintf(stdout,\"%%c\",pop());fflush(stdout); goto " RIGHT ";\n", x, y, x_right, y);
|
|
317 |
fprintf(fo, LEFT ": fprintf(stdout,\"%%c\",pop());fflush(stdout); goto " LEFT ";\n", x, y, x_left, y);
|
|
318 |
fprintf(fo, UP ": fprintf(stdout,\"%%c\",pop());fflush(stdout); goto " UP ";\n", x, y, x, y_up);
|
|
319 |
fprintf(fo, DOWN ": fprintf(stdout,\"%%c\",pop());fflush(stdout); goto " DOWN ";\n", x, y, x, y_down);
|
296 | 320 |
break;
|
297 | 321 |
case '&':
|
298 | |
fprintf(fo, RIGHT ": fscanf(stdin,\"%cld\",&b);push(b); goto " RIGHT ";\n", x, y, '%', x_right, y);
|
299 | |
fprintf(fo, LEFT ": fscanf(stdin,\"%cld\",&b);push(b); goto " LEFT ";\n", x, y, '%', x_left, y);
|
300 | |
fprintf(fo, UP ": fscanf(stdin,\"%cld\",&b);push(b); goto " UP ";\n", x, y, '%', x, y_up);
|
301 | |
fprintf(fo, DOWN ": fscanf(stdin,\"%cld\",&b);push(b); goto " DOWN ";\n", x, y, '%', x, y_down);
|
|
322 |
fprintf(fo, RIGHT ": fscanf(stdin,\"%%ld\",&b);push(b); goto " RIGHT ";\n", x, y, x_right, y);
|
|
323 |
fprintf(fo, LEFT ": fscanf(stdin,\"%%ld\",&b);push(b); goto " LEFT ";\n", x, y, x_left, y);
|
|
324 |
fprintf(fo, UP ": fscanf(stdin,\"%%ld\",&b);push(b); goto " UP ";\n", x, y, x, y_up);
|
|
325 |
fprintf(fo, DOWN ": fscanf(stdin,\"%%ld\",&b);push(b); goto " DOWN ";\n", x, y, x, y_down);
|
302 | 326 |
break;
|
303 | 327 |
case '~':
|
304 | 328 |
fprintf(fo, RIGHT ": c=fgetc(stdin);push(c); goto " RIGHT ";\n", x, y, x_right, y);
|
|
307 | 331 |
fprintf(fo, DOWN ": c=fgetc(stdin);push(c); goto " DOWN ";\n", x, y, x, y_down);
|
308 | 332 |
break;
|
309 | 333 |
case '"': /* ha! */
|
310 | |
ECHO("puts(\"Error: compiled Befunge does not support stringmode\n\");");
|
|
334 |
ECHO("puts(\"Error: compiled Befunge does not support stringmode\\n\");");
|
311 | 335 |
break;
|
312 | 336 |
case '!':
|
313 | 337 |
ECHO("if(pop()) push(0); else push(1);");
|
|
320 | 344 |
break;
|
321 | 345 |
case '?':
|
322 | 346 |
fprintf(fo, ALL, x, y, x, y, x, y, x, y);
|
323 | |
fprintf(fo, " switch ((rand () / 32) %c 4) \n"
|
|
347 |
fprintf(fo, " switch ((rand () / 32) %% 4) \n"
|
324 | 348 |
" { case 0: goto " RIGHT ";\n"
|
325 | 349 |
" case 1: goto " LEFT ";\n"
|
326 | 350 |
" case 2: goto " UP ";\n"
|
327 | 351 |
" case 3: goto " DOWN "; }\n",
|
328 | |
'%', x_right, y, x_left, y, x, y_up, x, y_down);
|
|
352 |
x_right, y, x_left, y, x, y_up, x, y_down);
|
329 | 353 |
break;
|
330 | 354 |
case '#':
|
331 | 355 |
fprintf(fo, RIGHT ": goto " RIGHT ";\n", x, y, x_2right, y);
|
|
415 | 439 |
}
|
416 | 440 |
}
|
417 | 441 |
}
|
418 | |
fclose (fi);
|
419 | |
fclose (fo);
|
|
442 |
if (fi) fclose (fi);
|
|
443 |
if (fo) fclose (fo);
|
420 | 444 |
if ((fi = fopen ("temp.c", "r")) != NULL)
|
421 | 445 |
{
|
422 | 446 |
if ((fo = fopen (argv[argc - 1], "w")) != NULL)
|