1 #include <stdlib.h> 2 #include <unistd.h> 3 #include <string.h> 4 #include <stdio.h> 5 #include <math.h> 6 7 int main(int argc, char **argv) { 8 char buf[2048], *buf_p, *tmp, *val; 9 char *outbuf = NULL, *outbuf_p = NULL; 10 char *filename; 11 char *sect = NULL, *cmd; 12 FILE *fp; 13 long long arg; 14 long long code_size; 15 size_t buflen; 16 int cs_byte = 0; 17 int invalid_data = 0; 18 int retval = 0; 19 int linenumber = 0; 20 size_t i, outbuf_len, highest_outbuf, iv_dest, iv_loc; 21 int intnum; 22 23 if (argc != 2) { 24 printf("Usage: sfc <filename>\n"); 25 return(1); 26 } 27 28 filename = argv[1]; 29 fp = fopen(filename, "r"); 30 31 if (!fp) { 32 fprintf(stderr, "Error opening file (%s).\n", filename); 33 perror("fopen"); 34 return(1); 35 } 36 37 while (1) { 38 if (invalid_data) { 39 fprintf(stderr, "Error compiling %s (at line %i), aborting.\n", filename, linenumber); 40 break; 41 } 42 43 fgets(buf, sizeof(buf), fp); 44 if (feof(fp)) { 45 break; 46 } 47 48 buf[sizeof(buf) - 1] = '\0'; 49 50 linenumber++; 51 52 buf_p = buf; 53 54 /* Trim off any leading spaces */ 55 while (*buf_p == ' ' || *buf_p == '\t') { 56 buf_p++; 57 } 58 59 /* COmments indicate end of line/string. */ 60 tmp = strchr(buf_p, '#'); 61 if (tmp) { 62 *tmp = '\0'; 63 } 64 65 /* Determine the length of the line. */ 66 buflen = strlen(buf_p); 67 if (buflen < 1) { 68 continue; 69 } 70 71 /* Trim off pesky newline charectars. */ 72 if (buf_p[buflen - 1] == '\n') { 73 buf_p[buflen - 1] = '\0'; 74 buflen--; 75 } 76 77 /* Skip blank lines */ 78 if (buflen == 0) { 79 continue; 80 } 81 82 if (*buf_p == '[') { 83 /* Process sections */ 84 85 if (sect) { 86 free(sect); 87 } 88 89 tmp = buf_p + 1; 90 tmp[strlen(tmp) - 1] = '\0'; 91 sect = strdup(tmp); 92 93 if (strcmp(sect, "init") == 0) { 94 } else if (strcmp(sect, "main") == 0) { 95 outbuf_p = outbuf + 1; 96 } else if (strcmp(sect, "data") == 0) { 97 outbuf_p = outbuf + 1 + code_size + 1024; 98 } else { 99 if (strncmp(sect, "int", 3) == 0) { 100 intnum = atoi(sect + 3); 101 iv_dest = outbuf_p - outbuf; 102 iv_loc = 1 + code_size + (4 * intnum); 103 104 outbuf[iv_loc] = (iv_dest >> 24) & 0xff; 105 outbuf[iv_loc + 1] = (iv_dest >> 16) & 0xff; 106 outbuf[iv_loc + 2] = (iv_dest >> 8) & 0xff; 107 outbuf[iv_loc + 3] = iv_dest & 0xff; 108 } else { 109 invalid_data = 1; 110 continue; 111 } 112 } 113 114 continue; 115 } else { 116 if (!sect) { 117 invalid_data = 1; 118 continue; 119 } 120 121 122 if (strcmp(sect, "init") == 0) { 123 cmd = buf_p; 124 tmp = strpbrk(cmd, " \t"); 125 if (tmp) { 126 *tmp = '\0'; 127 tmp++; 128 arg = strtoll(tmp, NULL, 0); 129 } else { 130 arg = -1; 131 } 132 133 /* Process directives */ 134 if (strcmp(cmd, "code_size") == 0) { 135 cs_byte = log(arg / 1024) / log(2) + 0.999; 136 137 if (cs_byte <= 0 || cs_byte >= 256) { 138 invalid_data = 1; 139 continue; 140 } 141 142 code_size = pow(2, cs_byte) * 1024; 143 144 outbuf_len = 1 + code_size + 1024 + (640 * 1024); 145 outbuf = calloc(outbuf_len, 1); 146 outbuf_p = outbuf; 147 148 if (!outbuf) { 149 invalid_data = 1; 150 continue; 151 } 152 153 *outbuf_p = cs_byte; outbuf_p++; 154 } else { 155 invalid_data = 1; 156 continue; 157 } 158 } else if (strcmp(sect, "data") == 0) { 159 /* Save direct data */ 160 161 for (tmp = buf_p; (val = strsep(&tmp, " \t"));) { 162 arg = strtoll(val, NULL, 16); 163 *outbuf_p = arg; outbuf_p++; 164 } 165 } else { 166 cmd = buf_p; 167 tmp = strpbrk(cmd, " \t"); 168 if (tmp) { 169 *tmp = '\0'; 170 tmp++; 171 arg = strtoll(tmp, NULL, 0); 172 } else { 173 arg = -1; 174 } 175 176 /* 177 * The "init" section must come before 178 * anything else, abandon otherwise. 179 */ 180 if (!outbuf) { 181 invalid_data = 1; 182 continue; 183 } 184 185 /* Process commands */ 186 if (strcmp(cmd, "add") == 0) { 187 if (arg == -1) { 188 arg = 1; 189 } 190 *outbuf_p = '+'; outbuf_p++; 191 *outbuf_p = arg; outbuf_p++; 192 } else if (strcmp(cmd, "sub") == 0) { 193 if (arg == -1) { 194 arg = 1; 195 } 196 197 *outbuf_p = '-'; outbuf_p++; 198 *outbuf_p = arg; outbuf_p++; 199 } else if (strcmp(cmd, "left") == 0) { 200 if (arg == -1) { 201 arg = 1; 202 } 203 204 *outbuf_p = '<'; outbuf_p++; 205 *outbuf_p = arg; outbuf_p++; 206 } else if (strcmp(cmd, "right") == 0) { 207 if (arg == -1) { 208 arg = 1; 209 } 210 211 *outbuf_p = '>'; outbuf_p++; 212 *outbuf_p = arg; outbuf_p++; 213 } else if (strcmp(cmd, "loop_begin") == 0) { 214 *outbuf_p = '['; outbuf_p++; 215 *outbuf_p = 0; outbuf_p++; 216 } else if (strcmp(cmd, "loop_end") == 0) { 217 *outbuf_p = ']'; outbuf_p++; 218 *outbuf_p = 0; outbuf_p++; 219 } else if (strcmp(cmd, "int") == 0) { 220 if (arg == -1) { 221 invalid_data = 1; 222 continue; 223 } 224 225 *outbuf_p = '*'; outbuf_p++; 226 *outbuf_p = arg; outbuf_p++; 227 } else if (strcmp(cmd, "ret") == 0) { 228 *outbuf_p = '!'; outbuf_p++; 229 *outbuf_p = 0; outbuf_p++; 230 } else { 231 invalid_data = 1; 232 continue; 233 } 234 } 235 } 236 237 } 238 239 fclose(fp); 240 241 if (!invalid_data) { 242 for (i = outbuf_len; i >= 0; i--) { 243 if (outbuf[i]) { 244 highest_outbuf = i; 245 break; 246 } 247 } 248 249 for (i = 0; i <= highest_outbuf; i++) { 250 write(STDOUT_FILENO, outbuf + i, 1); 251 } 252 } else { 253 retval = 1; 254 } 255 256 return(retval); 257 } |