s502 assembler
A very simple assembler for the 6502 line of processors written in C
Functions
tokenFunc.c File Reference

implement token member methods More...

#include "debugmalloc.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "tokenFunc.h"
#include "util.h"
#include "number.h"
#include "state.h"
#include "logging.h"
#include "directive.h"

Go to the source code of this file.

Functions

void token_print (Token *token)
 
int token_analyze_instruction (State *s, Token *t)
 
int token_recognize (Token *t)
 
int token_get_operand (State *s, Token *t)
 
int token_compile (State *s, Token *t, char **dataptr)
 

Detailed Description

implement token member methods

See also
tokenFunc.h

Definition in file tokenFunc.c.

Function Documentation

◆ token_analyze_instruction()

int token_analyze_instruction ( State s,
Token t 
)

Definition at line 224 of file tokenFunc.c.

224  {
225  if (token_link_instruction(s, t) < 0) {
226  ERROR("Unknown instruction!\n");
227  goto ERR;
228  }
229  if (token_get_addressmode(t) < 0) {
230  ERROR("Can not determine instruction address mode!\n");
231  goto ERR;
232  }
233  if (t->instr.inst->opcs[t->instr.addressmode] == OPC_INVALID) {
234  ERROR("Invalid instruction-addressmode combination!\n");
235  ERROR("A-mode: %s\n", ADRM_NAMES[t->instr.addressmode]);
236  goto ERR;
237  }
238 
239  t->binSize = 1 + ADRM_SIZES[t->instr.addressmode];
240 
241  return 0;
242 
243 
244 ERR:
245  token_print(t);
246  FAIL("Error while analyzing token: \n");
247  return -1;
248 }

References ADRM_NAMES, ADRM_SIZES, Token::binSize, ERROR, FAIL, Token::instr, OPC_INVALID, Token::token_get_addressmode(), Token::token_link_instruction(), and Token::token_print().

◆ token_compile()

int token_compile ( State s,
Token t,
char **  dataptr 
)

Definition at line 318 of file tokenFunc.c.

318  {
319  if (t->type != TT_INSTR) {
320  if (t->type == TT_DIRECTIVE) {
321  return directive_compile(s, t, dataptr);
322  }
323  // should NEVER reach this:
324  ERROR("Something went terribly wrong!\n");
325  ERROR("A LABEL in last pass!\n");
326  return -1;
327  }
328  int size = t->binSize;
329  char* data = malloc(size);
330  *dataptr = data;
331  if (t->instr.addressmode == ADRM_REL) {
332  int n = t->instr.number - t->instr.address - 2;
333 
334  if (-128 > n || 127 < n) {
335  ERROR("Relative addressing jump too far!\n");
336  printf("Target: $%x, from: $%x (diff: $%x)\n", t->instr.number, t->instr.address, n);
337  token_print(t);
338  free(data);
339  *dataptr = NULL;
340  return -1;
341  }
342  t->instr.number = n;
343  }
344  data[0] = t->instr.inst->opcs[t->instr.addressmode];
345  if (size > 1) {
346  data[1] = t->instr.number & 0xff;
347  }
348  if (size > 2) {
349  data[2] = (t->instr.number >> 8) & 0xff;
350  }
351  return 0;
352 }

References ADRM_REL, Token::binSize, directive_compile(), ERROR, Token::instr, Token::token_print(), TT_DIRECTIVE, TT_INSTR, and Token::type.

◆ token_get_operand()

int token_get_operand ( State s,
Token t 
)

Definition at line 287 of file tokenFunc.c.

287  {
288  if (t->type != TT_INSTR) return 0;
289  if (t->binSize == 1) {
290  t->instr.number = 0;
291  return 0;
292  }
293 
294  char* begin = &t->stripped[4];
295  char* end;
296  for (; *begin != 0 && (*begin == ' ' || *begin == '*' || *begin == '(' || *begin == '#'); begin++);
297  for (end = begin; *end != 0 && *end != ')' && *end != ',' && *end != ' '; end++);
298 
299  char* buff = malloc(end - begin + 1);
300  strncpy(buff, begin, end - begin + 1);
301  buff[end - begin] = 0;
302 
303  int n = number_get_number(s, buff);
304  free(buff);
305 
306  if (n == NUMBER_ERROR) {
307  token_print(t);
308  FAIL("Opcode operand parsing failed!\n");
309  return -1;
310  }
311  if (n == NUMBER_LABEL_NODEF) {
312  return 0;
313  }
314  t->instr.number = n;
315  return 0;
316 }

References Token::binSize, FAIL, Token::instr, NUMBER_ERROR, number_get_number(), NUMBER_LABEL_NODEF, Token::stripped, Token::token_print(), TT_INSTR, and Token::type.

◆ token_print()

void token_print ( Token token)

Definition at line 20 of file tokenFunc.c.

20  {
21  printf("\t%s:%d:%d\t\t'%.*s'\n", token->source.fname, token->source.lineno, token->len, token->len, token->stripped);
22 }

References Token::len, Token::source, and Token::stripped.

◆ token_recognize()

int token_recognize ( Token t)

Definition at line 251 of file tokenFunc.c.

251  {
252  // how many token types does it fit
253  int found = 0;
254 
255  // directive - starts with a dot
256  if (t->stripped[0] == '.') {
257  t->type = TT_DIRECTIVE;
258  found++;
259  }
260 
261  // label - ends with a ':'
262  if (t->stripped[t->len - 1] == ':') {
263  t->type = TT_LABEL;
264  found++;
265  }
266 
267  // instruction - 3rd char is a space or len is 3
268  if (t->stripped[3] == ' ' || t->stripped[3] == '\0') {
269  t->type = TT_INSTR;
270  t->instr.number = -1;
271  found++;
272  }
273 
274  // 0 or more than one match is a problem
275  if (found != 1) {
276  ERROR("Can not recognize token:\n");
277  token_print(t);
278  return -1;
279  }
280 
281  LOG(4, "Recognized token as %d:\n", t->type);
282  LOGDO(4, token_print(t));
283 
284  return 0;
285 }

References ERROR, Token::instr, Token::len, LOG, LOGDO, Token::stripped, Token::token_print(), TT_DIRECTIVE, TT_INSTR, TT_LABEL, and Token::type.

TT_INSTR
@ TT_INSTR
instruction token
Definition: token_t.h:26
Token::instr
struct Token::@1 instr
instruction data. Not used if token type is not TT_INSTR
ADRM_NAMES
const char * ADRM_NAMES[]
Human-readable names of address modes.
Definition: addressmode.c:16
Token::stripped
char stripped[TOKEN_BUFFER_SIZE]
stripped text from source file
Definition: token_t.h:55
ADRM_REL
@ ADRM_REL
Relative (8bit, signed 2's complement)
Definition: addressmode.h:39
Token::token_link_instruction
int token_link_instruction(State *s, Token *token)
find and link the instruction entry for a token
Definition: tokenFunc.c:30
Token::token_get_addressmode
int token_get_addressmode(Token *t)
Determine the address mode of a token.
Definition: tokenFunc.c:109
LOG
#define LOG(LVL,...)
logging macro - works like printf
Definition: logging.h:28
LOGDO
#define LOGDO(LVL, x)
Conditional macro. Wraps contents into a conditional based on log level.
Definition: logging.h:35
ADRM_SIZES
int ADRM_SIZES[ADRM_COUNT+1]
operand sizes of addressmodes
Definition: addressmode.c:37
Token::binSize
int binSize
number of bytes this token will generate
Definition: token_t.h:39
TT_DIRECTIVE
@ TT_DIRECTIVE
directive token
Definition: token_t.h:28
Token::type
enum tokenType type
type of this token
Definition: token_t.h:41
Token::token_print
void token_print(Token *token)
Pretty-print one token, with its source and length.
Definition: tokenFunc.c:20
directive_compile
int directive_compile(State *s, Token *t, char **dataptr)
Compile a directive into binary data.
Definition: directive.c:498
TT_LABEL
@ TT_LABEL
label token
Definition: token_t.h:30
Token::source
struct Token::@2 source
source of this token
Token::len
int len
length of stripped text
Definition: token_t.h:57
NUMBER_ERROR
@ NUMBER_ERROR
Could not parse a number or constant is undefined.
Definition: number.h:15
number_get_number
int number_get_number(State *s, char *str)
interpret a string as a constant, label or number
Definition: number.c:75
OPC_INVALID
@ OPC_INVALID
An invalid opcode to signal invalid / non-existent variations.
Definition: instructions.h:15
FAIL
#define FAIL(...)
Fancy-print a fail (failed step). Works like printf.
Definition: logging.h:45
ERROR
#define ERROR(...)
Fancy-print an error (cause of faliure). Works like printf.
Definition: logging.h:40
NUMBER_LABEL_NODEF
@ NUMBER_LABEL_NODEF
Undefined label.
Definition: number.h:17