meow.git

meow.c

espurr
/* meow - 6502 assembler
 * Copyright (C) 2024-2025 ArcNyxx
 * see LICENCE file for licensing information */

#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "direct.h"
#include "instruct.h"
#include "label.h"
#include "meow.h"

static char *fname;
static size_t fline;
char ps[0xffff] = { 0 };
uint16_t pc = 0;

void
meow(const char *msg, ...)
{
	fputs("meow: ", stderr);

	va_list ap;
	va_start(ap, msg);
	vfprintf(stderr, msg, ap);
	va_end(ap);

	if (msg[strlen(msg) - 1] == ' ')
		perror(NULL);
	else
		fprintf(stderr, ": %s:%lu\n", fname, fline);
}

bool
islabel(const char *label)
{
        if (!isalpha(label[0]) && label[0] != '_')
                return false;
        for (size_t i = 1; label[i] != '\0'; ++i)
                if (!isalnum(label[i]) && label[i] != '_')
                        return false;
        return true;
}


long
strnum(const char *str, char **endptr)
{
	int base = 10;
	const char *place = str;
	if (str[0] == '%') {
		base = 2;
		++place;
	} else if (str[0] == '$') {
		base = 16;
		++place;
	}
	errno = 0;
	return strtol(place, endptr, base);
}

int
main(int argc, char **argv)
{
	char *line = NULL;
	size_t size = 0;
	for (int i = 1; i < argc; ++i) {
		FILE *fp;
		fname = argv[i];
		if ((fp = fopen(fname, "r")) == NULL) {
			meow("fatal: unable to open file: %s: ", fname);
			return 1;
		}

		for (errno = 0, fline = 1; getline(&line, &size, fp) >= 1;
				errno = 0, ++fline) {
			char *semi;
			if ((semi = strchr(line, ';')) != NULL)
				semi[0] = '\0'; /* ignore comment */
			char *str;
			if ((str = strtok(line, " \t\n\r")) == NULL)
				continue;

			if (str[0] == '.') {
				direct(str);
			} else if (str[strlen(str) - 1] == ':') {
				str[strlen(str) - 1] = '\0';
				labeldef(str, pc);
			} else {
				instruct(str);
			}
		}
		if (errno) {
			meow("fatal: unable to continue reading file: %s: ",
					fname);
			return 1;
		}

		fclose(fp);
	}

	labelchk();
	fwrite(ps, 0xffff, 1, stdout);
}