The preprocessor is a text based way of modifying the input before
the assembly step.
+Preprocessor directives start with a # and have to be the first non-space character in a line.
+All lines that are not a preprocessor directive, or are not part of a preprocessor block (macro, or if)
+will be output as-is. If a line contains the name of a preprocessot define or macro
+,surrounded by token any character that is not alphanumeric or an underscore,
+the define or macro will be expanded.
+
Withing preprocessor macros
- $0 will expand to the literal argument string
- $1 to $9 will expand to the comma separated arguments of the macro
Macros:
-#macro
+#macro my_macro
label$$:
adc $1, $2
-#endm
+#endmacro
+
+my_macro a, b
-.SH ASSEMBLY SYNTAX
+.SH ASSEMBLY SYNTAX
+
.SH EXAMPLES
--- /dev/null
+#ifndef PREPROC_H_
+#define PREPROC_H_
+
+#include <stdio.h>
+
+/*
+ * Preprocessor
+ */
+
+enum ulas_ppdefs {
+ ULAS_PP_DEF,
+ ULAS_PP_MACRO,
+};
+
+struct ulas_ppdef {
+ enum ulas_ppdefs type;
+};
+
+/**
+ * Tokenize and apply the preprocessor
+ */
+int ulas_preproc(FILE *dst, FILE *src);
+
+#endif
union ulas_tokdat dat;
};
-enum ulas_ppdirs {
- ULAS_PP_DEF,
- ULAS_PP_MACRO,
-};
-
-struct ulas_ppdir {
- enum ulas_ppdirs type;
-};
-
/**
* Symbols
*/
int ulas_main(struct ulas_config cfg);
+char *ulas_strndup(const char *src, size_t n);
+
/**
- * Tokenize and apply the preprocessor
+ * A token rule returns true when a token should end
+ * otherwise returns false
*/
-int ulas_preproc(FILE *dst, FILE *src);
+typedef bool (*ulas_tokrule)(char current, char prev);
-char *ulas_strndup(const char *src, size_t n);
+// simple tokenizer at any space char
+bool ulas_tokrulespace(char current, char prev);
+
+// tokenisze according to pre-defined rules
+// returns the amount of bytes of line that were
+// consumed or -1 on error
+// returns 0 when no more tokens can be read
+int ulas_tok(char *dst, const char *line, size_t n, ulas_tokrule rule);
#endif
BIN_INSTALL_DIR=/usr/local/bin
MAN_INSTALL_DIR=/usr/local/man
-_OBJ = $(MAIN) ulas.o
+_OBJ = $(MAIN) ulas.o preproc.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
all: bin test
--- /dev/null
+#include "preproc.h"
+
+
+int ulas_preproc(FILE *dst, FILE *src) { return 0; }
#include "ulas.h"
#include <stdio.h>
+#include <assert.h>
-void null_test_success(void) {
- puts("[null test]");
- puts("[null test ok]");
+#define TESTBEGIN(name) printf("[test %s]\n", (name));
+#define TESTEND(name) printf("[%s ok]\n", (name));
+
+#define assert_tok(expected_tok, expected_ret, line, rule) \
+ { \
+ char buf[256]; \
+ memset(buf, 0, 256); \
+ assert(ulas_tok(buf, (line), 256, (rule)) == (expected_ret)); \
+ assert(strcmp(buf, expected_tok) == 0); \
+ }
+
+void test_tok(void) {
+ TESTBEGIN("tok");
+
+ assert_tok("test", 4, "test tokens", ulas_tokrulespace);
+ assert_tok("tokens", 6, "tokens", ulas_tokrulespace);
+ assert_tok("", 0, "", ulas_tokrulespace);
+ assert_tok("", -1, NULL, ulas_tokrulespace);
+
+ TESTEND("tok");
}
int main(int arc, char **argv) {
fclose(stderr);
}
- null_test_success();
+ test_tok();
return 0;
}
#include "ulas.h"
+#include <ctype.h>
#include <errno.h>
#include <string.h>
return 0;
}
-int ulas_preproc(FILE *dst, FILE *src) {}
+bool ulas_tokrulespace(char current, char prev) { return isspace(current); }
+
+int ulas_tok(char *dst, const char *line, size_t n, ulas_tokrule rule) {
+ if (!dst || !line || n == 0) {
+ return -1;
+ }
+
+ int i = 0;
+ char prev = '\0';
+ char current = '\0';
+ for (i = 0; i < n - 1 && line[i]; i++) {
+ prev = current;
+ current = line[i];
+ if (rule(current, prev)) {
+ break;
+ }
+ dst[i] = current;
+ }
+
+ dst[i + 1] = '\0';
+ return i;
+}