* © 2018 Aaron Taylor <ataylor at subgeniuskitty dot com>
* See LICENSE.txt file for copyright and license details.
#include "nedasm_structures.h"
#include "nedasm_parser_extensions.h"
seek_newline(uint32_t * linenum
, FILE * input
)
while ((c
= fgetc(input
)) != EOF
) {
parse_mnemonic(uint32_t * linenum
, FILE * input
, struct instruction
* instructions
)
char mnemonic
[MAX_MNEMONIC_LEN
];
size_t mnemonic_index
= 0;
char label
[MAX_LABEL_LEN
];
while ((c
= fgetc(input
)) != EOF
) {
if (c
== '_' || c
== '+' || c
== '>') {
if (mnemonic_index
>= MAX_MNEMONIC_LEN
-2) { /* -2 to reserve space for '\0'. */
fprintf(stderr
, "ERROR: Violating MAX_MNEMONIC_LEN on line %d.\n", *linenum
);
mnemonic
[mnemonic_index
++] = c
;
if (data_index
>= MAX_DATA_LEN
-2) { /* -2 to reserve space for '\0'. */
fprintf(stderr
, "ERROR: Violating MAX_DATA_LEN on line %d.\n", *linenum
);
if (label_index
>= MAX_LABEL_LEN
-2) { /* -2 to reserve space for '\0'. */
fprintf(stderr
, "ERROR: Violating MAX_LABEL_LEN on line %d.\n", *linenum
);
label
[label_index
++] = c
;
mnemonic
[mnemonic_index
] = '\0';
label
[label_index
] = '\0';
if (c
== EOF
) ungetc(EOF
, input
);
struct instruction
* new_instruction
= create_instruction_struct();
new_instruction
->linenum
= *linenum
;
if (strncmp(mnemonic
, "WORD", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= WORD
;
new_instruction
->data
= strtoimax(data
, NULL
, 10);
} else if (strncmp(mnemonic
, "IM", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= IM
;
new_instruction
->data
= strtoimax(data
, NULL
, 10);
} else if (strncmp(mnemonic
, "LDSP", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= LDSP
;
new_instruction
->data
= strtoimax(data
, NULL
, 10);
} else if (strncmp(mnemonic
, "STSP", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= STSP
;
new_instruction
->data
= strtoimax(data
, NULL
, 10);
} else if (strncmp(mnemonic
, "MVSTCK", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= MVSTCK
;
} else if (strncmp(mnemonic
, "ADD", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= ADD
;
} else if (strncmp(mnemonic
, "XOR", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= XOR
;
} else if (strncmp(mnemonic
, "NOT", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= NOT
;
} else if (strncmp(mnemonic
, "OR", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= OR
;
} else if (strncmp(mnemonic
, "AND", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= AND
;
} else if (strncmp(mnemonic
, "BRZ", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= WORD
;
new_instruction
->target
= malloc(label_index
+1);
strncpy(new_instruction
->target
, label
, label_index
+1);
new_instruction
->next
= create_instruction_struct();
new_instruction
->next
->prev
= new_instruction
;
new_instruction
->next
->syllable
= BRZ
;
new_instruction
->linenum
= *linenum
;
new_instruction
->syllable
= BRZ
;
} else if (strncmp(mnemonic
, "TEST", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= TEST
;
} else if (strncmp(mnemonic
, "CMPSWP", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= CMPSWP
;
} else if (strncmp(mnemonic
, "SHIFT", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= SHIFT
;
} else if (strncmp(mnemonic
, "STORE", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= STORE
;
} else if (strncmp(mnemonic
, "LOAD", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= LOAD
;
} else if (strncmp(mnemonic
, "NOP", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= NOP
;
} else if (strncmp(mnemonic
, "HALT", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= HALT
;
} else if (strncmp(mnemonic
, "JMP", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= WORD
;
new_instruction
->target
= malloc(label_index
+1);
strncpy(new_instruction
->target
, label
, label_index
+1);
new_instruction
->next
= create_instruction_struct();
new_instruction
->next
->prev
= new_instruction
;
new_instruction
->next
->syllable
= JMP
;
new_instruction
->linenum
= *linenum
;
new_instruction
->syllable
= JMP
;
} else if (strncmp(mnemonic
, "SWAP", MAX_MNEMONIC_LEN
) == 0) {
new_instruction
->syllable
= SWAP
;
/* Fake/composite mnemonics. Not part of the NED ISA. */
new_instruction
= parse_pseudo_mnemonic(mnemonic
, mnemonic_index
, data
, data_index
,
label
, label_index
, new_instruction
);
if (new_instruction
->syllable
== 0) {
fprintf(stderr
, "ERROR: Unable to match mnemonic on line %d.\n", *linenum
);
if (instructions
!= NULL
) {
instructions
= seek_instruction_list_end(instructions
);
new_instruction
= seek_instruction_list_start(new_instruction
);
new_instruction
->prev
= instructions
;
instructions
->next
= new_instruction
;
instructions
= new_instruction
;
instructions
= seek_instruction_list_end(instructions
);
parse_dest_label(uint32_t * linenum
, FILE * input
, struct instruction
* instructions
)
instructions
= seek_instruction_list_end(instructions
);
char word
[MAX_LABEL_LEN
];
while ((c
= fgetc(input
)) != EOF
) {
/* TODO: Accept underscores or hyphens inside labels. */
if (i
>= MAX_LABEL_LEN
) {
fprintf(stderr
, "ERROR: Exceeded max label length on line %d.\n", *linenum
);
struct instruction
* new_instruction
= create_instruction_struct();
new_instruction
->syllable
= LABEL
;
new_instruction
->linenum
= *linenum
;
new_instruction
->label
= malloc(i
+1);
strncpy(new_instruction
->label
, word
, i
+1);
if (instructions
!= NULL
) {
instructions
->next
= new_instruction
;
new_instruction
->prev
= instructions
;
instructions
= new_instruction
;
parse_assembly(struct instruction
** instructions
, FILE * input
)
while ((c
= fgetc(input
)) != EOF
) {
seek_newline(&linenum
, input
);
} else if (c
== ' ' || c
== '\t') {
/* Intentionally empty in order to skip whitespace. */
} else if (isupper(c
)) { /* Mnemonics start with uppercase alpha char. */
*instructions
= parse_mnemonic(&linenum
, input
, *instructions
);
} else if (islower(c
)) { /* Labels start with lowercase alpha char. */
*instructions
= parse_dest_label(&linenum
, input
, *instructions
);
fprintf(stderr
, "ERROR: Invalid syntax on line %d\n", linenum
);