asm.c (2707B)
1 #include <u.h> 2 #include <libc.h> 3 4 #include "vsm.h" 5 6 typedef struct Label Label; 7 struct Label { 8 char *name; 9 CELL addr; 10 }; 11 12 Label *labels = nil; 13 long lc = 0; 14 15 char **tokens = nil; 16 long memc = 0; 17 18 void 19 usage(void) 20 { 21 fprint(2, "usage: %s code.va\n", argv0); 22 exits("usage"); 23 } 24 25 void 26 pushtoken(char *t) 27 { 28 tokens = realloc(tokens, (memc + 1) * sizeof(char*)); 29 tokens[memc] = strdup(t); 30 memc++; 31 } 32 33 void 34 pushtokens(char *buf) 35 { 36 char **argv; 37 int i, argc; 38 argv = malloc(sizeof(char*) * 32); 39 argc = tokenize(buf, argv, 32); 40 for (i = 0; i < argc; i++) pushtoken(argv[i]); 41 free(argv); 42 } 43 44 void 45 pushlabel(char *name, CELL addr) 46 { 47 labels = realloc(labels, sizeof(Label) * (lc+1)); 48 labels[lc].name = strdup(name); 49 labels[lc].addr = addr; 50 lc++; 51 } 52 53 void 54 pass1(char *fname) 55 { 56 int fid; 57 int lcount; 58 char buf[256], *bp; 59 fid = open(fname, OREAD); 60 if (fid < 0) { 61 fprint(2, "failed to open file %s\n", fname); 62 exits("no file"); 63 } 64 lcount = 1; 65 bp = buf; 66 while((read(fid, bp, 1)) > 0) 67 { 68 if (*bp == '\n'){ 69 *bp = 0; 70 switch(buf[0]){ 71 case 0: 72 /* empty line, do nothing */ 73 case '`': 74 /* comment, do nothing */ 75 break; 76 case ':': 77 /* label */ 78 pushlabel(buf + 2, memc); 79 break; 80 case '\t': 81 case ' ': 82 /* tokens */ 83 pushtokens(buf); 84 break; 85 default: 86 fprint(2, "%s:%d unknown directive: %s\n", 87 fname, lcount, buf); 88 exits("bad source"); 89 } 90 lcount++; 91 bp = buf; 92 } 93 else { 94 bp++; 95 } 96 } 97 close(fid); 98 } 99 100 int 101 label(char *s) 102 { 103 int i; 104 for (i = 0; i < lc; i++) { 105 if (strncmp(s, labels[i].name, strlen(s)) == 0) { 106 write(1, &labels[i].addr, sizeof(CELL)); 107 return 0; 108 } 109 } 110 return -1; 111 } 112 113 int 114 number(char *s) 115 { 116 CELL n; 117 char *p; 118 n = strtol(s, &p, 10); 119 if (p == s) return -1; 120 write(1, &n, sizeof(CELL)); 121 return 0; 122 } 123 124 void 125 pass2(void) 126 { 127 int i; 128 for (i = 0; i < memc; i++) { 129 if (label(tokens[i]) == 0) continue; 130 if (number(tokens[i]) < 0) { 131 fprint(2, "addr:%d not a number: %s\n", 132 i, tokens[i]); 133 exits("bad source"); 134 } 135 } 136 } 137 138 void 139 main(int argc, char **argv) 140 { 141 ARGBEGIN{ 142 default: 143 usage(); 144 break; 145 }ARGEND 146 if (argc != 1) usage(); 147 148 pushlabel("no", VSM_NOP); 149 pushlabel("ad", VSM_ADD); 150 pushlabel("su", VSM_SUB); 151 pushlabel("an", VSM_AND); 152 pushlabel("or", VSM_OR); 153 pushlabel("xo", VSM_XOR); 154 pushlabel("dr", VSM_DROP); 155 pushlabel("du", VSM_DUP); 156 pushlabel("ov", VSM_OVER); 157 pushlabel("sw", VSM_SWAP); 158 pushlabel("to", VSM_TOR); 159 pushlabel("fr", VSM_FROMR); 160 pushlabel("st", VSM_STORE); 161 pushlabel("fe", VSM_FETCH); 162 pushlabel("li", VSM_LIT); 163 pushlabel("if", VSM_IF); 164 pushlabel("ca", VSM_CALL); 165 pushlabel("ex", VSM_EXIT); 166 pushlabel("pu", VSM_PUTC); 167 pushlabel("ge", VSM_GETC); 168 169 pass1(argv[0]); 170 pass2(); 171 }