vsm

virtual stack machine for plan9
git clone git://nsmpr.xyz/vsm.git
Log | Files | Refs

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 }