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

file reading, tokenization and token recognition step More...

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include "loadfile.h"
#include "token_t.h"
#include "tokenFunc.h"
#include "logging.h"

Go to the source code of this file.

Functions

int read_token (FILE *f, Token *t)
 magic token reader function More...
 
TokensListread_file (char *name)
 read all tokens from a file More...
 
TokensListload_file (char *name)
 load and parse one file More...
 

Detailed Description

file reading, tokenization and token recognition step

Full read step

Definition in file loadfile.c.

Function Documentation

◆ load_file()

TokensList* load_file ( char *  name)

load and parse one file

Load file, parse into tokens, build TokensList, identify token types

Parameters
namefile name / path to load
Returns
list of tokens in file or NULL on error

Definition at line 166 of file loadfile.c.

166  {
167  LOG(3, "Reading file...\n");
168 
169  TokensList* list = read_file(name);
170  if (list == NULL)
171  goto ERROR;
172 
173  LOG(3, "Running first analysis...\n");
174  if (tokenslist_recognize(list) < 0)
175  goto ERROR;
176 
177  return list;
178 
179 ERROR:
180  FAIL("Failed to load file contents: '%s'\n", name);
181  tokenslist_free(list);
182  return NULL;
183 }

References ERROR, FAIL, LOG, read_file(), TokensList::tokenslist_free(), and TokensList::tokenslist_recognize().

Referenced by main().

◆ read_file()

TokensList* read_file ( char *  name)

read all tokens from a file

Parameters
namefile name to read tokens from
Returns
list of all tokens or NULL on error

High-level func to read the contents from a file

  • reads file contents
  • parses every line as a token
  • generates token list
  • returns said token list
  • returns NULL on error

Definition at line 119 of file loadfile.c.

119  {
120 
121  // basic file open
122  FILE* f = fopen(name, "r");
123  if (f == NULL) {
124  ERROR("An error occured opening the file %s!\n", name);
125  ERROR("Error opening file: %s\n", strerror(errno));
126  return NULL;
127  }
128 
129  TokensList* tokenslist = tokenslist_new();
130  if (tokenslist == NULL) goto ERR_MEM;
131  Token tok;
132  int lineno = 1;
133  int res;
134 
135  // reading tokens while possible
136  do {
137  res = read_token(f, &tok);
138  if (tok.len > 0) {
139  strncpy(tok.source.fname, name, TOKEN_SOURCE_FILE_SIZE - 1);
140  tok.source.fname[TOKEN_SOURCE_FILE_SIZE - 1] = 0;
141  tok.source.lineno = lineno;
142  if (tokenslist_add(tokenslist, tok) < 0) goto ERR_MEM;
143  }
144  lineno++;
145  } while (res > 0);
146 
147  fclose(f);
148 
149  // return error if stopped due to reading error
150  if (res < 0) {
151  ERROR("line is too long!\n");
152  token_print(&tok);
153  tokenslist_free(tokenslist);
154  return NULL;
155  }
156  return tokenslist;
157 ERR_MEM:
158 
159  FAIL("read_file() failed!\n");
160  fclose(f);
161  tokenslist_free(tokenslist);
162  return NULL;
163 }

References ERROR, FAIL, Token::len, read_token(), Token::source, Token::token_print(), TOKEN_SOURCE_FILE_SIZE, TokensList::tokenslist_add(), TokensList::tokenslist_free(), and TokensList::tokenslist_new().

Referenced by load_file().

◆ read_token()

int read_token ( FILE *  f,
Token t 
)

magic token reader function

Parameters
ffile to read from
ttoken to read into
Returns
1 on success, 0 on EOF and -1 on error

Read a single token into a Token struct from file f

  • read relevant part
  • return 1 on success, 0 on EOF and -1 on error Internal workings:
  • read characters into puffer
  • only write one whitespace
  • don't write ; and any characters after
  • stop on EOF and

Definition at line 33 of file loadfile.c.

33  {
34  t->binSize = 0;
35 
36  int seen_whitespace = 1, eol = 0;
37  int ptr, c;
38 
39  // -1 for trailing nullbyte
40  for (ptr = 0; ptr < TOKEN_BUFFER_SIZE - 1;) {
41  // read char
42  c = fgetc(f);
43 
44  // stop condition
45  if (c == EOF || c == '\n') {
46  break;
47  }
48 
49  if (c == '\r') continue; // damn line endings!
50 
51  // don't write if already reached a comment
52  if (eol)
53  continue;
54 
55  // whitespace handling
56  if (c == '\t' || c == ' ') {
57  if (!seen_whitespace) {
58  c = ' ';
59  seen_whitespace = 1;
60  } else {
61  continue;
62  }
63  } else { // all othet chars
64  seen_whitespace = 0;
65 
66  // mark comment
67  if (c == ';') {
68  eol = 1;
69  continue;
70  }
71  }
72 
73  // tha actual write
74  // continues skipt this
75  t->stripped[ptr++] = c;
76  }
77 
78  // too long line
79  if (ptr == TOKEN_BUFFER_SIZE - 1) {
80  t->len = ptr;
81  return -1;
82  }
83 
84  // kill trailing whitespace
85  if (t->stripped[ptr - 1] == ' ')
86  ptr--;
87 
88  // zero-terminate
89  t->stripped[ptr] = 0;
90  // len
91  t->len = ptr;
92  t->instr.number = 0;
93 
94  // log
95  if (ptr > 0) {
96  LOG(5, "READ TOKEN:\n");
97  LOGDO(5, token_print(t));
98  }
99 
100  // EOF return
101  if (c == EOF)
102  return 0;
103 
104  return 1;
105 }

References Token::binSize, Token::instr, Token::len, LOG, LOGDO, Token::stripped, TOKEN_BUFFER_SIZE, and Token::token_print().

Referenced by read_file().

TokensList::tokenslist_free
void tokenslist_free(TokensList *list)
free ALL memory associated with the TokensList object
Definition: tokenslist.c:78
read_file
TokensList * read_file(char *name)
read all tokens from a file
Definition: loadfile.c:119
Token::instr
struct Token::@1 instr
instruction data. Not used if token type is not TT_INSTR
Token::stripped
char stripped[TOKEN_BUFFER_SIZE]
stripped text from source file
Definition: token_t.h:55
TokensList::tokenslist_add
int tokenslist_add(TokensList *list, Token t)
Append a token to the list.
Definition: tokenslist.c:31
TOKEN_SOURCE_FILE_SIZE
@ TOKEN_SOURCE_FILE_SIZE
source filename max length. Longer strings will get truncated.
Definition: token_t.h:15
LOG
#define LOG(LVL,...)
logging macro - works like printf
Definition: logging.h:28
TOKEN_BUFFER_SIZE
@ TOKEN_BUFFER_SIZE
Token max length.
Definition: token_t.h:13
LOGDO
#define LOGDO(LVL, x)
Conditional macro. Wraps contents into a conditional based on log level.
Definition: logging.h:35
Token
Token type to store token information.
Definition: token_t.h:37
Token::binSize
int binSize
number of bytes this token will generate
Definition: token_t.h:39
TokensList::tokenslist_recognize
int tokenslist_recognize(TokensList *t)
Do token recognition on all tokens in a list.
Definition: tokenslist.c:117
TokensList
A doubly-linked list for storing Tokens.
Definition: tokenslist.h:29
Token::token_print
void token_print(Token *token)
Pretty-print one token, with its source and length.
Definition: tokenFunc.c:20
Token::source
struct Token::@2 source
source of this token
Token::len
int len
length of stripped text
Definition: token_t.h:57
read_token
int read_token(FILE *f, Token *t)
magic token reader function
Definition: loadfile.c:33
TokensList::tokenslist_new
TokensList * tokenslist_new()
Create a new (empty) TokensList object.
Definition: tokenslist.c:17
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