usynth

simple midi synth for sndio
git clone git://nsmpr.xyz/usynth.git
Log | Files | Refs

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 }