meow.git
label.c
/* meow - 6502 assembler
* Copyright (C) 2024-2025 ArcNyxx
* see LICENCE file for licensing information */
#include <ctype.h>
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "label.h"
#include "meow.h"
typedef struct pos {
struct pos *next;
uint16_t ind;
asiz_t type;
} pos_t;
typedef struct label {
struct label *next;
pos_t *pos;
char *name;
uint16_t val;
bool defined;
} label_t;
static label_t *labels;
extern char ps[0xffff];
static pos_t *
initpos(const uint16_t ind, const asiz_t type)
{
pos_t *ret;
if ((ret = malloc(sizeof(pos_t))) == NULL) {
meow("fatal: unable to allocate memory: ");
exit(1);
}
ret->next = NULL;
ret->ind = ind;
ret->type = type;
return ret;
}
static label_t *
initlabel(const char *name, const uint16_t val, const bool defined)
{
label_t *ret;
if ((ret = malloc(sizeof(label_t))) == NULL) {
meow("fatal: unable to allocate memory: ");
exit(1);
}
ret->next = NULL;
ret->pos = NULL;
ret->name = strdup(name);
ret->val = val;
ret->defined = defined;
return ret;
}
static void
resolve(const uint16_t val, const uint16_t ind, const asiz_t type)
{
switch (type) {
default:
break;
case BIT16:
ps[ind] = val & 0xff;
ps[ind + 1] = (val & 0xff00) >> 2;
break;
case BIT8:
if (val > 0xff)
meow("error: zero page address being truncated: "
"%x at %x", val, ind);
ps[ind] = val & 0xff;
break;
case REL: ;
int16_t diff = (int16_t)val - (int16_t)ind - 1;
if (diff > SCHAR_MAX || diff < SCHAR_MIN)
meow("error: relative jump too far: %x to %x",
ind, val);
ps[ind] = diff & 0xff;
}
}
void
labeldef(const char *name, const uint16_t val)
{
for (label_t *label = labels; label != NULL; label = label->next)
if (!strcmp(label->name, name)) {
label->val = val;
if (label->defined) {
meow("warn: label redefined: %s", name);
return;
}
label->defined = true;
while (label->pos != NULL) {
resolve(label->val, label->pos->ind,
label->pos->type);
pos_t *tmp = label->pos;
label->pos = label->pos->next;
free(tmp);
}
return;
}
label_t *label = initlabel(name, val, true);
label->next = labels;
labels = label;
}
void
labeladd(const char *name, const uint16_t ind, asiz_t type)
{
for (label_t *label = labels; label != NULL; label = label->next)
if (!strcmp(label->name, name)) {
if (label->defined) {
resolve(label->val, ind, type);
} else {
pos_t *pos = initpos(ind, type);
pos->next = label->pos;
label->pos = pos;
}
return;
}
label_t *label = initlabel(name, 0, false);
label->pos = initpos(ind, type);
label->next = labels;
labels = label;
}
void
labelchk(void)
{
for (label_t *label = labels; label != NULL; label = label->next)
if (label->pos != NULL)
meow("error: label undefined: %s", label->name);
}