summaryrefslogtreecommitdiff
path: root/cpp.c
blob: aeebaa8bb48c381efd9f8b635994776840818827 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
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;
}