Browse Source

Implement ROM version; reading 8- and 16-bit ints.

master
Ben Kurtovic 9 years ago
parent
commit
174a8c24a1
3 changed files with 69 additions and 48 deletions
  1. +60
    -45
      src/assembler/parse_util.c
  2. +2
    -0
      src/assembler/parse_util.h
  3. +7
    -3
      src/assembler/preprocessor.c

+ 60
- 45
src/assembler/parse_util.c View File

@@ -8,12 +8,57 @@
#include "directives.h"

/*
Read in an integer starting at str and ending the character before end.
Read in a boolean argument from the given line and store it in *result.

Store the value in *result and return true on success; else return false.
auto_val is used if the argument's value is "auto". Return true on success
and false on failure; in the latter case, *result is not modified.
*/
static inline bool read_integer(uint32_t *result, const char *str, const char *end)
bool parse_bool(bool *result, const ASMLine *line, const char *directive, bool auto_val)
{
const char *arg = line->data + (DIRECTIVE_OFFSET(line, directive) + 1);
ssize_t len = line->length - (DIRECTIVE_OFFSET(line, directive) + 1);

if (len <= 0 || len > 5)
return false;

switch (len) {
case 1: // 0, 1
if (*arg == '0' || *arg == '1')
return (*result = *arg - '0'), true;
return false;
case 2: // on
if (!strncmp(arg, "on", 2))
return (*result = true), true;
return false;
case 3: // off
if (!strncmp(arg, "off", 3))
return (*result = false), true;
return false;
case 4: // true, auto
if (!strncmp(arg, "true", 4))
return (*result = true), true;
if (!strncmp(arg, "auto", 4))
return (*result = auto_val), true;
return false;
case 5: // false
if (!strncmp(arg, "false", 5))
return (*result = false), true;
return false;
}
return false;
}

/*
Read in a 32-bit int argument from the given line and store it in *result.

Return true on success and false on failure; in the latter case, *result is
not modified.
*/
bool parse_uint32(uint32_t *result, const ASMLine *line, const char *directive)
{
const char *str = line->data + (DIRECTIVE_OFFSET(line, directive) + 1);
const char *end = str + (line->length - (DIRECTIVE_OFFSET(line, directive) + 1));

if (end - str <= 0)
return false;

@@ -30,7 +75,7 @@ static inline bool read_integer(uint32_t *result, const char *str, const char *e
value = (value * 0x10) + 0xA + (*str - 'a');
else
return false;
if (value >= UINT32_MAX)
if (value > UINT32_MAX)
return false;
str++;
}
@@ -40,7 +85,7 @@ static inline bool read_integer(uint32_t *result, const char *str, const char *e
if (*str < '0' || *str > '9')
return false;
value = (value * 10) + (*str - '0');
if (value >= UINT32_MAX)
if (value > UINT32_MAX)
return false;
str++;
}
@@ -51,59 +96,29 @@ static inline bool read_integer(uint32_t *result, const char *str, const char *e
}

/*
Read in a boolean argument from the given line and store it in *result.
Read in a 16-bit int argument from the given line and store it in *result.

auto_val is used if the argument's value is "auto". Return true on success
and false on failure; in the latter case, *result is not modified.
Return true on success and false on failure; in the latter case, *result is
not modified.
*/
bool parse_bool(bool *result, const ASMLine *line, const char *directive, bool auto_val)
bool parse_uint16(uint16_t *result, const ASMLine *line, const char *directive)
{
const char *arg = line->data + (DIRECTIVE_OFFSET(line, directive) + 1);
ssize_t len = line->length - (DIRECTIVE_OFFSET(line, directive) + 1);

if (len <= 0 || len > 5)
return false;

switch (len) {
case 1: // 0, 1
if (*arg == '0' || *arg == '1')
return (*result = *arg - '0'), true;
return false;
case 2: // on
if (!strncmp(arg, "on", 2))
return (*result = true), true;
return false;
case 3: // off
if (!strncmp(arg, "off", 3))
return (*result = false), true;
return false;
case 4: // true, auto
if (!strncmp(arg, "true", 4))
return (*result = true), true;
if (!strncmp(arg, "auto", 4))
return (*result = auto_val), true;
return false;
case 5: // false
if (!strncmp(arg, "false", 5))
return (*result = false), true;
return false;
}
uint32_t value;
if (parse_uint32(&value, line, directive) && value <= UINT16_MAX)
return (*result = value), true;
return false;
}

/*
Read in a 32-bit int argument from the given line and store it in *result.
Read in an 8-bit int argument from the given line and store it in *result.

Return true on success and false on failure; in the latter case, *result is
not modified.
*/
bool parse_uint32(uint32_t *result, const ASMLine *line, const char *directive)
bool parse_uint8(uint8_t *result, const ASMLine *line, const char *directive)
{
const char *arg = line->data + (DIRECTIVE_OFFSET(line, directive) + 1);
ssize_t len = line->length - (DIRECTIVE_OFFSET(line, directive) + 1);

uint32_t value;
if (read_integer(&value, arg, arg + len))
if (parse_uint32(&value, line, directive) && value <= UINT8_MAX)
return (*result = value), true;
return false;
}

+ 2
- 0
src/assembler/parse_util.h View File

@@ -10,3 +10,5 @@

bool parse_bool(bool*, const ASMLine*, const char*, bool);
bool parse_uint32(uint32_t*, const ASMLine*, const char*);
bool parse_uint16(uint16_t*, const ASMLine*, const char*);
bool parse_uint8(uint8_t*, const ASMLine*, const char*);

+ 7
- 3
src/assembler/preprocessor.c View File

@@ -299,8 +299,9 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source)

ASMLine dummy = {.next = state->lines};
ASMLine *prev, *line = &dummy, *next = state->lines, *condemned = NULL;

const ASMLine *first_optimizer = NULL, *first_checksum = NULL,
*first_product = NULL;
*first_product = NULL, *first_version = NULL;

while ((prev = line, line = next)) {
next = line->next;
@@ -338,8 +339,11 @@ ErrorInfo* preprocess(AssemblerState *state, const LineBuffer *source)
CATCH_DUPES(line, first_product, state->header.product_code, arg)
}
else if (IS_DIRECTIVE(line, DIR_ROM_VERSION)) {
// TODO
// state->header.version <-- range check
REQUIRE_ARG(line, DIR_ROM_VERSION)
uint8_t arg;
VALIDATE(parse_uint8(&arg, line, DIR_ROM_VERSION))
RANGE_CHECK(arg, 0x10)
CATCH_DUPES(line, first_version, state->header.version, arg)
}
else if (IS_DIRECTIVE(line, DIR_ROM_REGION)) {
// TODO


Loading…
Cancel
Save