build.c (3360B)
1 #include <stdio.h> 2 #include <limits.h> 3 #include <stdlib.h> 4 #include <string.h> 5 6 #include "util.h" 7 #include "machine.h" 8 #include "build.h" 9 10 const Label builtin[] = { 11 /* vm memory mapping */ 12 {"VM_PC", VM_PC}, 13 {"VM_ACTIVE", VM_ACTIVE}, 14 {"VM_HALTED", VM_HALTED}, 15 {"VM_KEY", VM_KEY}, 16 {"VM_KEY_ON", VM_KEY_ON}, 17 {"VM_OPERATORS", VM_OPERATORS}, 18 {"VM_SP", VM_SP}, 19 {"VM_STACK", VM_STACK}, 20 {"VM_PROG_START", VM_PROG_START}, 21 {"VM_MEM_END", VM_MEM_END}, 22 }; 23 24 25 void 26 splittokens(char *dat, Array *tokens) 27 { 28 char *sp, *p; 29 sp = dat; 30 for (p = dat; *p != '\0'; p++) { 31 if (*p == '\n') { 32 Token *tok; 33 *p = '\0'; 34 p++; 35 tok = arrayinc(tokens); 36 *tok = (struct Token){*sp, sp+1}; 37 sp = p; 38 } 39 } 40 } 41 42 void 43 addwords(Array *words, char *p) 44 { 45 char *w; 46 while(p != NULL) { 47 w = strsep(&p, " \t"); 48 if (*w != '\0') { 49 char **n; 50 n = arrayinc(words); 51 *n = w; 52 } 53 } 54 } 55 56 int 57 run1(Array *tokens, Array *labels, Array *words) 58 { 59 struct Token *tok; 60 struct Label *l; 61 char *np, *vp, *ep; 62 int v, i; 63 for (i = 0; i < tokens->n; i++) { 64 tok = arrayget(tokens, i); 65 switch (tok->t) { 66 case '\t': 67 case ' ': 68 addwords(words, tok->p); 69 break; 70 case ':': 71 np = strsep(&tok->p, " \t"); 72 vp = strsep(&tok->p, " \t"); 73 if (vp != NULL) { 74 v = strtol(vp, &ep, 16); 75 if (vp == ep) { 76 fprintf(stderr, "%s?\n", vp); 77 return -1; 78 } 79 } else v = words->n + VM_PROG_START; 80 l = arrayinc(labels); 81 *l = (Label){np, v}; 82 break; 83 case '\0': 84 case '#': 85 break; 86 default: 87 fprintf(stderr, "%c%s?\n", 88 tok->t, tok->p); 89 } 90 } 91 return 0; 92 } 93 94 Label * 95 getlabel(Array *labels, char *p) 96 { 97 int i; 98 Label *l; 99 for (i = 0; i < labels->n; i++) { 100 l = arrayget(labels, i); 101 if (strcmp(l->p, p) == 0) return l; 102 } 103 return NULL; 104 } 105 106 107 int 108 run2(Array *labels, Array *words, int16_t *prog) 109 { 110 int i; 111 if (words->n > VM_MEM_END - VM_PROG_START) { 112 fprintf(stderr, "not enough memory\n"); 113 return -1; 114 } 115 for (i = 0; i < words->n; i++) { 116 Label *l; 117 int16_t *p; 118 char **w; 119 w = arrayget(words, i); 120 p = &prog[i + VM_PROG_START]; 121 l = getlabel(labels, *w); 122 if (l != NULL) { 123 *p = l->n; 124 } else { 125 char *ep; 126 int16_t n; 127 n = strtol(*w, &ep, 16); 128 if ((*w == ep)||(*ep != '\0')) { 129 fprintf(stderr, "%s?\n", *w); 130 return -1; 131 } 132 *p = n; 133 } 134 } 135 return 0; 136 } 137 138 int 139 build(char *dat, int16_t *prog) 140 { 141 int i, r; 142 Array *tokens; 143 Array *labels; 144 Array *words; 145 146 r = 0; 147 148 tokens = newarray(sizeof(Token)); 149 labels = newarray(sizeof(Label)); 150 words = newarray(sizeof(char *)); 151 152 labels->n = sizeof(builtin)/sizeof(*builtin); 153 labels->p = realloc(labels->p, sizeof(builtin)); 154 memcpy(labels->p, builtin, sizeof(builtin)); 155 156 for (i = 0; vm_iset[i].instr != NULL; i++) { 157 Label *l; 158 l = arrayinc(labels); 159 *l = (Label) {vm_iset[i].name, i}; 160 } 161 162 splittokens(dat, tokens); 163 if ((run1(tokens, labels, words) != 0) || 164 (run2(labels, words, prog) != 0)) { 165 fprintf(stderr, "build failed\n"); 166 r = -1; 167 } 168 freearray(tokens); 169 freearray(labels); 170 freearray(words); 171 return r; 172 } 173 174 int 175 buildfile(FILE *fp, int16_t *prog) 176 { 177 char *buf, *bp; 178 size_t n, s; 179 int r; 180 s = 1024; 181 buf = malloc(s); 182 bp = buf; 183 while ((n = fread(bp, 1024, 1, fp)) > 0) { 184 s += n; 185 buf = realloc(buf, s + 1024); 186 bp = buf + s; 187 } 188 if (n < 0) { 189 fprintf(stderr, "failed to read file\n"); 190 return -1; 191 } 192 r = build(buf, prog); 193 free(buf); 194 return r; 195 }