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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
#include "dseg.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DSEG_PANIC(msg) {fprintf(stderr, "dseg error: " msg "\n"); exit(1);}
#define STRING_PATTERN "str%llu"
static integral_t string_counter = 0;
static integral_t hash_string(const char* str, integral_t cap) {
integral_t hash = 0, i = 0;
while (str[i] != 0) ADVANCE_HASH(hash, str[i++], cap);
return hash;
}
static integral_t hash_ent(const struct dseg_entry* ent, integral_t cap) {
switch (ent->type) {
case ENT_STRING:
return hash_string(ent->key.string, cap);
}
DSEG_PANIC("hash function not defined for entry type");
}
static bool ent_eq(const struct dseg_entry* a, const struct dseg_entry* b) {
if (a->type != b->type) return false;
switch (a->type) {
case ENT_STRING:
return strcmp(a->key.string, b->key.string) == 0;
}
DSEG_PANIC("equality function not defined for entry type");
}
static void ent_destroy(struct dseg_entry* entry) {
free(entry->symbol);
}
void dseg_init(struct hash_map* dseg) {
hm_init(
dseg,
(hm_hash_fn) hash_ent,
(hm_eq_fn) ent_eq,
(hm_destroy_fn) ent_destroy);
}
void dseg_destroy(struct hash_map* dseg) {
hm_destroy(dseg);
}
static void ent_assign_key(struct dseg_entry* ent) {
switch (ent->type) {
case ENT_STRING:
integral_t strnum = string_counter++;
int req_sz = snprintf(NULL, 0, STRING_PATTERN, strnum);
if (req_sz < 0) CCC_PANIC;
req_sz += 1; // null terminator
ent->symbol = ccc_alloc(req_sz);
snprintf(ent->symbol, req_sz, STRING_PATTERN, strnum);
break;
}
}
const char* dseg_put(struct hash_map* dseg, struct dseg_entry entry) {
struct dseg_entry** cell = (struct dseg_entry**) hm_cell_w(dseg, &entry);
if (*cell != NULL) return (*cell)->symbol;
struct dseg_entry* new_ent = ccc_alloc(sizeof(struct dseg_entry));
*cell = new_ent;
*new_ent = entry;
ent_assign_key(new_ent);
return new_ent->symbol;
}
static inline bool is_printable(char c) {
return ' ' <= c && c <= '~';
}
void emit_string_data(FILE* outfile, const struct dseg_entry* ent) {
const char* str = ent->key.string;
fprintf(outfile, "db ");
for (integral_t i = 0; str[i] != 0;) {
if (is_printable(str[i])) {
fprintf(outfile, "\"%c", str[i]);
while (is_printable(str[++i])) fputc(str[i], outfile);
fprintf(outfile, "\", ");
} else {
fprintf(outfile, "0x%x, ", str[i++]);
}
}
fprintf(outfile, "0x0");
}
void emit_dseg(FILE* outfile, const struct hash_map* dseg) {
fprintf(outfile, "section .data\n");
for (integral_t i = 0; i < dseg->cap; i++) {
const struct dseg_entry* ent = dseg->entries[i];
if (ent == NULL) continue;
fprintf(outfile, "\t%s ", ent->symbol);
switch (ent->type) {
case ENT_STRING:
emit_string_data(outfile, ent);
break;
}
fprintf(outfile, "\n");
}
}
|