summaryrefslogtreecommitdiff
path: root/cpp.c
diff options
context:
space:
mode:
Diffstat (limited to 'cpp.c')
-rw-r--r--cpp.c91
1 files changed, 91 insertions, 0 deletions
diff --git a/cpp.c b/cpp.c
new file mode 100644
index 0000000..aeebaa8
--- /dev/null
+++ b/cpp.c
@@ -0,0 +1,91 @@
+#define _XOPEN_SOURCE 700
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "cc.h"
+#include "cpp.h"
+
+static void dump(struct macro *list)
+{
+ for (struct macro *p = list; p != NULL; p = p->next) {
+ if (p->file) {
+ printf("%s:%ju: ", p->file, p->line);
+ } else if (p->line == 0) {
+ printf("<BUILTIN>: ");
+ } else {
+ printf("<COMMAND LINE>: ");
+ }
+ printf("'%s' => '%s'\n", p->identifier, p->replacement);
+ }
+}
+
+int preprocess(const char *in, const char *out, struct macro *predefined)
+{
+ (void)in; (void)out;
+
+ time_t now = time(NULL);
+ struct tm *tm = localtime(&now);
+ char compiletime[16] = { 0 };
+ char compiledate[16] = { 0 };
+ strftime(compiletime, sizeof(compiletime), "%T", tm);
+ strftime(compiledate, sizeof(compiledate), "%b %e %Y", tm);
+
+ struct macro *perfile = define(NULL, NULL, 0, "__DATE__", compiledate);
+ define(perfile, NULL, 0, "__TIME__", compiletime);
+ define(perfile, NULL, 0, "__FILE__", in);
+ define(perfile, NULL, 0, "__LINE__", "0");
+
+ dump(predefined);
+ dump(perfile);
+
+ return 0;
+}
+
+static struct macro *do_define(struct macro *list, const char *file, uintmax_t line, const char *macro, const char *replacement)
+{
+ struct macro *def = list;
+
+ /* TODO: replace existing thing */
+ /* TODO: prevent redefining builtins */
+
+ if (def == NULL) {
+ def = calloc(1, sizeof(*def));
+ list = def;
+ } else {
+ while (def->next != NULL) {
+ def = def->next;
+ }
+ def->next = calloc(1, sizeof(*def));
+ def = def->next;
+ }
+
+ if (def == NULL) {
+ return NULL;
+ }
+
+ if (file) {
+ def->file = strdup(file);
+ if (file == NULL) {
+ return NULL;
+ }
+ }
+ def->line = line;
+ def->identifier = strdup(macro);
+ def->replacement = strdup(replacement);
+ if (def->identifier == NULL || def->replacement == NULL) {
+ return NULL;
+ }
+
+ return list;
+}
+
+struct macro *define(struct macro *list, const char *file, uintmax_t line, const char *macro, const char *replacement)
+{
+ list = do_define(list, file, line, macro, replacement);
+ if (list == NULL) {
+ error(file, line, "out of memory defining macro");
+ }
+ return list;
+}