about summary refs log tree commit diff
path: root/pps.c
blob: 1bcba888d3ad482ad12bcbef07e7b7bf0a91afa7 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
/*
 * Prototype Processor aSsembler
 *
 * Computer architecture is by qubane
 * Assembler is by nakidai and released in public domain
 */

#include <ctype.h>
#include <err.h>
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>


#define LINESZ 128

#define is(x, y) if (!strcmp((x), (y)))

char line[LINESZ];

void parsefile(const char *);

void emit(char inst)
{
	printf("%04b\n", (int)inst);
}

void tolowers(char *s)
{
	for (; *s; ++s)
		*s = tolower(*s);
}

int parsereg(const char *name)
{
	switch (*name)
	{
	case 'b': return 0;
	case 'm': return 1;
	case 'p': return 2;
	default:  return -1;
	}
}

void parseline(char *line, const char *path, size_t n)
{
	char *arg = strchr(line, ' '),
	     *end = strchr(line, '\n');

	arg && (*arg = 0);
	end && (*end = 0);

	if (!*line)
		return;

	tolowers(line);

	if (!arg++)
		is (line, "ca")       emit(8);
		else is (line, "add") emit(9);
		else is (line, "sub") emit(10);
		else is (line, "and") emit(11);
		else is (line, "or")  emit(12);
		else is (line, "xor") emit(13);
		else is (line, "rd")  emit(14);
		else is (line, "wt")  emit(15);
		else is (line, ";")   ;
		else errx(1, "%s:%d: invalid instruction: %s", path, n, line);
	else
		is (line, "lda")
			emit(atoi(arg));
		else is (line, "movc")
			if (tolowers(arg), parsereg(arg) < 0)
				errx(1, "%s:%lu: invalid instruction: %s %s", path, n, line, arg);
			else
				emit(4 + parsereg(arg));
		else is (line, "mov")
			if (tolowers(arg), parsereg(arg) != 0)
				errx(1, "%s:%lu: invalid instruction: %s %s", path, n, line, arg);
			else
				emit(7);
		else is (line, "inc") parsefile(arg);
		else is (line, ";");
		else errx(1, "%s:%lu invalid instruction: %s %s", path, n, line, arg);
}

void parsefile(const char *file)
{
	FILE *fp = fopen(file, "r");
	size_t n = 0;

	if (!fp)
		err(1, "fopen(%s)", file);

	while (fgets(line, sizeof(line), fp))
		parseline(line, file, n++);

	if (ferror(fp))
		err(1, "fgets(%s)", file);
}

int main(int argc, char **argv)
{
	if (!argv[1] || !*argv[1])
		return fprintf(stderr, "usage: %s <filename>\n", *argv), 1;
	parsefile(argv[1]);
}