4597919 [rkeene@sledge /home/rkeene/projects/bf/sf]$ cat -n sf.c
  1 #include <unistd.h>
  2 #include <stdlib.h>
  3 #include <string.h>
  4 #include <stdio.h>
  5 #include <math.h>
  6 
  7 struct sf_machine {
  8     size_t cs_size;
  9     unsigned char *buf;
 10     unsigned char *dp;
 11     size_t buflen;
 12     unsigned char flags_hlt;
 13     unsigned char *ip_stack[1024]; /* stack for handling instruction pointer */
 14     unsigned char **ip; /* current position in ip_stack */
 15 };
 16 
 17 typedef enum {
 18     INT_HLT = 0,
 19     INT_PRT = 1,
 20     INT_PRTC = 2,
 21     INT_GETC = 3
 22 } interrupt_t;
 23 
 24 void sf_dump(struct sf_machine *sys, const char *pre_msg, const char *post_msg) {
 25     size_t i, highest_offset;
 26 
 27         for (i = (sys->buflen - 1); i; i--) {
 28                 if (sys->buf[i]) {
 29                         highest_offset = i + 1;
 30                         break;
 31                 }
 32         }
 33 
 34     printf("********************************\n");
 35     if (pre_msg) {
 36         printf("%s\n", pre_msg);
 37     }
 38     printf("IPI = %i (%c)\n", (*sys->ip)[0], (*sys->ip)[0]);
 39     printf("IPA = %i\n", (*sys->ip)[1]);
 40     printf("IP = %llu\n", (unsigned long long) (*sys->ip - sys->buf) - 1);
 41     printf("DP = %llu\n", (unsigned long long) (sys->dp - sys->buf) - 1);
 42         printf("Contents of the buffer:\n");
 43         for (i = (sys->cs_size + 1 + 1024); i < highest_offset; i++) {
 44                 if ((i % 18) == 0) {
 45                         printf("   ");
 46                 }
 47                 printf("%c%3i,", ' ', sys->buf[i]);
 48                 if (((i + 1) % 18) == 0) {
 49                         printf("\n");
 50                 }
 51         }
 52         if (((i + 1) % 18) != 0) {
 53                 printf("\n");
 54         }
 55 
 56         printf("\n");
 57     if (post_msg) {
 58         printf("%s\n", post_msg);
 59     }
 60 }
 61 
 62 int sys_loadimage(const char *filename, struct sf_machine *sys) {
 63     unsigned char tmpbuf;
 64     size_t fread_ret;
 65     FILE *fp;
 66 
 67     fp = fopen(filename, "r");
 68     if (!fp) {
 69         return(-1);
 70     }
 71 
 72     fread_ret = fread(&tmpbuf, 1, 1, fp);
 73     if (fread_ret != 1) {
 74         fclose(fp);
 75         return(-1);
 76     }
 77 
 78     sys->cs_size = pow(2, tmpbuf) * 1024;
 79     /*
 80      * 640K ought to be enough for anybody.
 81      */
 82     sys->buflen = 1 + sys->cs_size + 1024 + (640 * 1024);
 83     sys->buf = malloc(sys->buflen);
 84     if (!sys->buf) {
 85         fclose(fp);
 86         return(-1);
 87     }
 88 
 89     memset(sys->buf, 0, sys->buflen);
 90 
 91     sys->buf[0] = tmpbuf;
 92     sys->ip_stack[0] = sys->buf + 1;
 93     sys->ip = sys->ip_stack;
 94     sys->dp = sys->buf + 1 + sys->cs_size + 1024;
 95 
 96     sys->buf++;
 97     while (1) {
 98         fread_ret = fread(sys->buf, 1, 8192, fp);
 99         if (fread_ret <= 0) {
100             break;
101         }
102         sys->buf += fread_ret;
103     }
104 
105     sys->buf = *sys->ip - 1;
106     sys->flags_hlt = 0;
107 
108     fclose(fp);
109 
110     if (fread_ret < 0) {
111         return(-1);
112     }
113 
114     return(0);
115 }
116 
117 void call_int(struct sf_machine *sys, unsigned char interrupt) {
118     switch ((interrupt_t) interrupt) {
119         case INT_HLT:
120             sys->flags_hlt = 1;
121             break;
122         case INT_PRT:
123             printf("%s", sys->dp);
124             break;
125         case INT_PRTC:
126             printf("%c", sys->dp[0]);
127             break;
128         case INT_GETC:
129             sys->dp[0] = getchar();
130             break;
131     }
132 
133     return;
134 }
135 
136 void sys_run(struct sf_machine *sys) {
137     unsigned char *buf;
138     unsigned char ipi, ipa;
139     unsigned long iv, iv_loc;
140     long test_depth;
141 
142     buf = sys->buf;
143 
144     while (1) {
145         ipi = (*sys->ip)[0];
146         ipa = (*sys->ip)[1];
147 
148         switch (ipi) {
149             case '+':
150                 (*sys->dp) += ipa;
151                 break;
152             case '-':
153                 (*sys->dp) -= ipa;
154                 break;
155             case '>':
156                 sys->dp += ipa;
157                 break;
158             case '<':
159                 sys->dp -= ipa;
160                 break;
161             case '[':
162                 if (!*sys->dp) {
163                     /*
164                      * If the value at (dp) is 0 then:
165                      * Move IP to the matching close brace
166                      * instruction
167                      */
168                     test_depth = 1;
169                     while (test_depth) {
170                         (*sys->ip)++;
171                         if (**sys->ip == '[') {
172                             test_depth++;
173                         } else if (**sys->ip == ']') {
174                             test_depth--;
175                         }
176                     }
177                 }   
178                 break;
179             case ']':
180                 if (*sys->dp) {
181                     /*
182                      * If the value at (dp) is non-zero then:
183                      * Move IP to the matching open brace
184                      * instruction.
185                      */
186                     test_depth = -1;
187                     while (test_depth) {
188                         (*sys->ip)--;
189                         if(**sys->ip == '[') {
190                             test_depth++;
191                         } else if (**sys->ip == ']') {
192                             test_depth--;
193                         }
194                     }
195                 }
196                 break;
197             case '*':
198                 iv_loc = sys->cs_size + 1 + (ipa * 4);
199                 iv = sys->buf[iv_loc] << 24;
200                 iv |= sys->buf[iv_loc + 1] << 16;
201                 iv |= sys->buf[iv_loc + 2] << 8;
202                 iv |= sys->buf[iv_loc + 3];
203 
204                 if (iv) {
205                     sys->ip++;
206                     *sys->ip = sys->buf + iv - 2;
207                 } else {
208                     call_int(sys, ipa);
209                 }
210                 break;
211             case '!':
212                 sys->ip--;
213                 break;
214             default:
215                 sys->flags_hlt = 1;
216                 break;
217         }
218 
219         if (sys->flags_hlt) {
220             break;
221         }
222 
223         (*sys->ip) += 2;
224     }
225 
226     return;
227 }
228 
229 int main(int argc, char **argv) {
230     struct sf_machine sf_sys;
231     char *image_name;
232     int retval;
233 
234     if (argc != 2) {
235         fprintf(stderr, "Usage: sf <image>\n");
236         return(EXIT_FAILURE);
237     }
238 
239     image_name = argv[1];
240 
241     retval = sys_loadimage(image_name, &sf_sys);
242     if (retval < 0) {
243         fprintf(stderr, "Error loading image.\n");
244         return(EXIT_FAILURE);
245     }
246 
247     sys_run(&sf_sys);
248 
249     fprintf(stderr, "***** HALTED *****\n");
250 
251     sf_dump(&sf_sys, NULL, NULL);
252 
253     return(EXIT_SUCCESS);
254 }
4597920 [rkeene@sledge /home/rkeene/projects/bf/sf]$

Click here to go back to the directory listing.
Click here to download this file.
last modified: 2008-07-24 19:49:03