Parcourir la source

Pass argparse args as a struct to make keeping track of deftabs easier.

master
Ben Kurtovic il y a 9 ans
Parent
révision
fdd8bb9e8a
7 fichiers modifiés avec 103 ajouts et 75 suppressions
  1. +15
    -12
      src/assembler/instructions.c
  2. +2
    -1
      src/assembler/instructions.h
  3. +56
    -52
      src/assembler/parse_util.c
  4. +14
    -6
      src/assembler/parse_util.h
  5. +10
    -0
      src/assembler/state.c
  6. +1
    -0
      src/assembler/state.h
  7. +5
    -4
      src/assembler/tokenizer.c

+ 15
- 12
src/assembler/instructions.c Voir le fichier

@@ -49,21 +49,20 @@

#define INST_FUNC(mnemonic) \
static ASMErrorDesc parse_inst_##mnemonic( \
uint8_t **bytes, size_t *length, char **symbol, const char *arg, size_t size)
uint8_t **bytes, size_t *length, char **symbol, ASMArgParseInfo ap_info) \

#define INST_ERROR(desc) return ED_PS_##desc;

#define INST_TAKES_NO_ARGS \
if (arg) \
if (ap_info.arg) \
INST_ERROR(TOO_MANY_ARGS) \
(void) size;

#define INST_TAKES_ARGS(lo, hi) \
if (!arg) \
if (!ap_info.arg) \
INST_ERROR(TOO_FEW_ARGS) \
ASMInstArg args[3]; \
size_t nargs = 0; \
ASMErrorDesc err = parse_args(args, &nargs, arg, size); \
ASMErrorDesc err = parse_args(args, &nargs, ap_info); \
if (err) \
return err; \
if (nargs < lo) \
@@ -143,14 +142,16 @@ static uint8_t fill_bytes_variadic(uint8_t *bytes, size_t len, ...)

Return ED_NONE (0) on success or an error code on failure.
*/
static ASMErrorDesc parse_arg(ASMInstArg *arg, const char *str, size_t size)
static ASMErrorDesc parse_arg(
ASMInstArg *arg, const char *str, size_t size, ASMDefineTable *deftable)
{
#define TRY_PARSER(func, argtype, field) \
if (argparse_##func(&arg->data.field, str, size)) { \
if (argparse_##func(&arg->data.field, info)) { \
arg->type = argtype; \
return ED_NONE; \
}

ASMArgParseInfo info = {.arg = str, .size = size, .deftable = deftable};
DEBUG("parse_arg(): -->%.*s<-- %zu", (int) size, str, size)
TRY_PARSER(register, AT_REGISTER, reg)
TRY_PARSER(immediate, AT_IMMEDIATE, imm)
@@ -164,22 +165,24 @@ static ASMErrorDesc parse_arg(ASMInstArg *arg, const char *str, size_t size)
}

/*
Parse an argument string int ASMInstArg objects.
Parse an argument string into ASMInstArg objects.

Return ED_NONE (0) on success or an error code on failure.
*/
static ASMErrorDesc parse_args(
ASMInstArg args[3], size_t *nargs, const char *str, size_t size)
ASMInstArg args[3], size_t *nargs, ASMArgParseInfo ap_info)
{
ASMErrorDesc err;
size_t start = 0, i = 0;
ASMDefineTable *dt = ap_info.deftable;
const char *str = ap_info.arg;
size_t size = ap_info.size, start = 0, i = 0;

while (i < size) {
char c = str[i];
if (c == ',') {
if (i == start)
return ED_PS_ARG_SYNTAX;
if ((err = parse_arg(&args[*nargs], str + start, i - start)))
if ((err = parse_arg(&args[*nargs], str + start, i - start, dt)))
return err;
(*nargs)++;

@@ -202,7 +205,7 @@ static ASMErrorDesc parse_args(
}

if (i > start) {
if ((err = parse_arg(&args[*nargs], str + start, i - start)))
if ((err = parse_arg(&args[*nargs], str + start, i - start, dt)))
return err;
(*nargs)++;
}


+ 2
- 1
src/assembler/instructions.h Voir le fichier

@@ -6,6 +6,7 @@
#include <stdint.h>

#include "errors.h"
#include "parse_util.h"

#define MIN_MNEMONIC_SIZE 2
#define MAX_MNEMONIC_SIZE 4
@@ -13,7 +14,7 @@
/* Typedefs */

typedef ASMErrorDesc (*ASMInstParser)(
uint8_t**, size_t*, char**, const char*, size_t);
uint8_t**, size_t*, char**, ASMArgParseInfo);

/* Functions */



+ 56
- 52
src/assembler/parse_util.c Voir le fichier

@@ -25,15 +25,15 @@
*/

/*
Adjust *arg_ptr / *size_ptr for an indirect argument, like (hl) or (ix+*).
Adjust *ap_info for an indirect argument, like (hl) or (ix+*).

*size_ptr must be > 2 to begin with, and is assured to be > 0 on success.
The two arguments are not modified on failure.
ap_info->size must be > 2 to begin with, and will always be > 0 on success.
*ap_info is not modified on failure.
*/
static bool adjust_for_indirection(const char **arg_ptr, ssize_t *size_ptr)
static bool adjust_for_indirection(ASMArgParseInfo *ap_info)
{
const char *arg = *arg_ptr;
ssize_t size = *size_ptr;
const char *arg = ap_info->arg;
ssize_t size = ap_info->size;

if (arg[0] != '(' || arg[size - 1] != ')')
return false;
@@ -50,8 +50,8 @@ static bool adjust_for_indirection(const char **arg_ptr, ssize_t *size_ptr)
return false;
}

*arg_ptr = arg;
*size_ptr = size;
ap_info->arg = arg;
ap_info->size = size;
return true;
}

@@ -208,19 +208,19 @@ bool parse_bytes(uint8_t **result, size_t *length, const char *arg, ssize_t size
/*
Read in a register argument and store it in *result.
*/
bool argparse_register(ASMArgRegister *result, const char *arg, ssize_t size)
bool argparse_register(ASMArgRegister *result, ASMArgParseInfo ai)
{
if (size < 1 || size > 3)
if (ai.size < 1 || ai.size > 3)
return false;

char buf[3] = {'\0'};
switch (size) {
case 3: buf[2] = LCASE(arg[2]);
case 2: buf[1] = LCASE(arg[1]);
case 1: buf[0] = LCASE(arg[0]);
switch (ai.size) {
case 3: buf[2] = LCASE(ai.arg[2]);
case 2: buf[1] = LCASE(ai.arg[1]);
case 1: buf[0] = LCASE(ai.arg[0]);
}

switch (size) {
switch (ai.size) {
case 1:
switch (buf[0]) {
case 'a': return (*result = REG_A), true;
@@ -263,18 +263,18 @@ bool argparse_register(ASMArgRegister *result, const char *arg, ssize_t size)
/*
Read in a condition argument and store it in *result.
*/
bool argparse_condition(ASMArgCondition *result, const char *arg, ssize_t size)
bool argparse_condition(ASMArgCondition *result, ASMArgParseInfo ai)
{
if (size < 1 || size > 2)
if (ai.size < 1 || ai.size > 2)
return false;

char buf[2] = {'\0'};
switch (size) {
case 2: buf[1] = LCASE(arg[1]);
case 1: buf[0] = LCASE(arg[0]);
switch (ai.size) {
case 2: buf[1] = LCASE(ai.arg[1]);
case 1: buf[0] = LCASE(ai.arg[0]);
}

switch (size) {
switch (ai.size) {
case 1:
switch (buf[0]) {
case 'n': return (*result = COND_N), true;
@@ -298,23 +298,25 @@ bool argparse_condition(ASMArgCondition *result, const char *arg, ssize_t size)
/*
Read in an immediate argument and store it in *result.
*/
bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size)
bool argparse_immediate(ASMArgImmediate *result, ASMArgParseInfo ai)
{
if (ai.size <= 0)
return false;

// TODO: lookup here for definition table

bool negative = false;
ssize_t i = 0;

if (size <= 0)
return false;

while (arg[i] == '-' || arg[i] == '+' || arg[i] == ' ') {
if (arg[i] == '-')
while (ai.arg[i] == '-' || ai.arg[i] == '+' || ai.arg[i] == ' ') {
if (ai.arg[i] == '-')
negative = !negative;
if (++i >= size)
if (++i >= ai.size)
return false;
}

uint32_t uval;
if (!parse_uint32_t(&uval, arg + i, size - i) || uval > UINT16_MAX)
if (!parse_uint32_t(&uval, ai.arg + i, ai.size - i) || uval > UINT16_MAX)
return false;

int32_t sval = negative ? -uval : uval;
@@ -351,20 +353,20 @@ bool argparse_immediate(ASMArgImmediate *result, const char *arg, ssize_t size)
/*
Read in an indirect argument and store it in *result.
*/
bool argparse_indirect(ASMArgIndirect *result, const char *arg, ssize_t size)
bool argparse_indirect(ASMArgIndirect *result, ASMArgParseInfo ai)
{
if (size < 3 || !adjust_for_indirection(&arg, &size))
if (ai.size < 3 || !adjust_for_indirection(&ai))
return false;

ASMArgRegister reg;
ASMArgImmediate imm;
if (argparse_register(&reg, arg, size)) {
if (argparse_register(&reg, ai)) {
if (reg == REG_BC || reg == REG_DE || reg == REG_HL) {
result->type = AT_REGISTER;
result->addr.reg = reg;
return true;
}
} else if (argparse_immediate(&imm, arg, size)) {
} else if (argparse_immediate(&imm, ai)) {
if (imm.mask & IMM_U16) {
result->type = AT_IMMEDIATE;
result->addr.imm = imm;
@@ -377,31 +379,31 @@ bool argparse_indirect(ASMArgIndirect *result, const char *arg, ssize_t size)
/*
Read in an indexed argument and store it in *result.
*/
bool argparse_indexed(ASMArgIndexed *result, const char *arg, ssize_t size)
bool argparse_indexed(ASMArgIndexed *result, ASMArgParseInfo ai)
{
if (size < 4 || !adjust_for_indirection(&arg, &size) || size < 2)
if (ai.size < 4 || !adjust_for_indirection(&ai) || ai.size < 2)
return false;

ASMArgRegister reg;
if (arg[0] != 'i')
if (ai.arg[0] != 'i')
return false;
if (arg[1] == 'x')
if (ai.arg[1] == 'x')
reg = REG_IX;
else if (arg[1] == 'y')
else if (ai.arg[1] == 'y')
reg = REG_IY;
else
return false;

arg += 2;
size -= 2;
if (size > 0 && arg[0] == ' ') {
arg++;
size--;
ai.arg += 2;
ai.size -= 2;
if (ai.size > 0 && ai.arg[0] == ' ') {
ai.arg++;
ai.size--;
}

if (size > 0) {
if (ai.size > 0) {
ASMArgImmediate imm;
if (!argparse_immediate(&imm, arg, size) || !(imm.mask & IMM_S8))
if (!argparse_immediate(&imm, ai) || !(imm.mask & IMM_S8))
return false;
result->offset = imm.sval;
} else {
@@ -414,20 +416,22 @@ bool argparse_indexed(ASMArgIndexed *result, const char *arg, ssize_t size)
/*
Read in a label argument and store it in *result.
*/
bool argparse_label(ASMArgLabel *result, const char *arg, ssize_t size)
bool argparse_label(ASMArgLabel *result, ASMArgParseInfo ai)
{
if (size >= MAX_SYMBOL_SIZE)
if (ai.size <= 0 || ai.size >= MAX_SYMBOL_SIZE)
return false;

for (const char *i = arg; i < arg + size; i++) {
// TODO: check for deftable

for (const char *i = ai.arg; i < ai.arg + ai.size; i++) {
char c = *i;
if (!((c >= 'a' && c <= 'z') || (i != arg && c >= '0' && c <= '9') ||
c == '_' || c == '.'))
if (!((c >= 'a' && c <= 'z') || c == '_' || c == '.' ||
(i != ai.arg && c >= '0' && c <= '9')))
return false;
}

strncpy(result->text, arg, size);
result->text[size] = '\0';
strncpy(result->text, ai.arg, ai.size);
result->text[ai.size] = '\0';
return true;
}



+ 14
- 6
src/assembler/parse_util.h Voir le fichier

@@ -11,6 +11,14 @@

#define dparse__Bool dparse_bool

/* Structs */

typedef struct {
const char *arg;
ssize_t size;
ASMDefineTable *deftable;
} ASMArgParseInfo;

/* Functions */

/* General parsers */
@@ -20,12 +28,12 @@ bool parse_string(char**, size_t*, const char*, ssize_t);
bool parse_bytes(uint8_t**, size_t*, const char*, ssize_t);

/* Instruction argument parsers */
bool argparse_register(ASMArgRegister*, const char*, ssize_t);
bool argparse_condition(ASMArgCondition*, const char*, ssize_t);
bool argparse_immediate(ASMArgImmediate*, const char*, ssize_t);
bool argparse_indirect(ASMArgIndirect*, const char*, ssize_t);
bool argparse_indexed(ASMArgIndexed*, const char*, ssize_t);
bool argparse_label(ASMArgLabel*, const char*, ssize_t);
bool argparse_register(ASMArgRegister*, ASMArgParseInfo);
bool argparse_condition(ASMArgCondition*, ASMArgParseInfo);
bool argparse_immediate(ASMArgImmediate*, ASMArgParseInfo);
bool argparse_indirect(ASMArgIndirect*, ASMArgParseInfo);
bool argparse_indexed(ASMArgIndexed*, ASMArgParseInfo);
bool argparse_label(ASMArgLabel*, ASMArgParseInfo);

/* Preprocessor directive parsers */
bool dparse_bool(bool*, const ASMLine*, const char*);


+ 10
- 0
src/assembler/state.c Voir le fichier

@@ -184,6 +184,16 @@ void asm_deftable_insert(ASMDefineTable *tab, ASMDefine *define)
hash_table_insert(tab, (HashNode*) define);
}

/*
Remove an ASMDefine from the define table.

Return true if the node was removed, or false if it was not found.
*/
bool asm_deftable_remove(ASMDefineTable *tab, const char *key)
{
return hash_table_remove(tab, key);
}

#ifdef DEBUG_MODE
/*
DEBUG FUNCTION: Print out an ASMLine list to stdout.


+ 1
- 0
src/assembler/state.h Voir le fichier

@@ -110,6 +110,7 @@ const ASMSymbol* asm_symtable_find(const ASMSymbolTable*, const char*);
void asm_symtable_insert(ASMSymbolTable*, ASMSymbol*);
const ASMDefine* asm_deftable_find(const ASMDefineTable*, const char*);
void asm_deftable_insert(ASMDefineTable*, ASMDefine*);
bool asm_deftable_remove(ASMDefineTable*, const char*);

#ifdef DEBUG_MODE
void asm_lines_print(const ASMLine*);


+ 5
- 4
src/assembler/tokenizer.c Voir le fichier

@@ -94,12 +94,13 @@ static ErrorInfo* add_label_to_table(
if (line->length - 1 >= MAX_SYMBOL_SIZE)
return error_info_create(line, ET_SYMBOL, ED_SYM_TOO_LONG);

ASMArgParseInfo info = {.arg = line->data, .size = line->length - 1};
ASMArgRegister reg;
if (argparse_register(&reg, line->data, line->length - 1))
if (argparse_register(&reg, info))
return error_info_create(line, ET_SYMBOL, ED_SYM_IS_REGISTER);

ASMArgCondition cond;
if (argparse_condition(&cond, line->data, line->length - 1))
if (argparse_condition(&cond, info))
return error_info_create(line, ET_SYMBOL, ED_SYM_IS_CONDITION);

char *symbol = strndup(line->data, line->length - 1);
@@ -301,8 +302,8 @@ static ErrorInfo* parse_instruction(
if (!parser)
return error_info_create(line, ET_PARSER, ED_PS_OP_UNKNOWN);

// TODO: pass deftab here?
ASMErrorDesc edesc = parser(&bytes, &length, &symbol, argstart, arglen);
ASMArgParseInfo ai = {.arg = argstart, .size = arglen, .deftable = deftab};
ASMErrorDesc edesc = parser(&bytes, &length, &symbol, ai);
if (edesc != ED_NONE)
return error_info_create(line, ET_PARSER, edesc);



Chargement…
Annuler
Enregistrer