aboutsummaryrefslogtreecommitdiff
path: root/csv_table_gen.c
blob: 859b85344963e93ca1ac98b043d9cfe3687dd90f (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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include <dirent.h>
#include <limits.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>

#define EXT ".csv"
#define EXT_LEN strlen(".csv")
#define CSV_PATH "csv"
#define OUT_PATH "analyzer/" CSV_PATH

#define BUFFER_SIZE 256
#define MAX_ARR_SIZE 4096

// read values from input csv and save them to buffers
// returns max_index of the array
int read_csv(char *path, char *from, char *to, char from_to_array[][BUFFER_SIZE]) {
    FILE *fp = fopen(path, "r");

    // read field names
    fscanf(fp, "%[^,],%[^\n]", from, to);

    // read values
    size_t max_index = 0;
    size_t val1;
    char val2[BUFFER_SIZE];
    while (fscanf(fp, "%zu,%[^\n]", &val1, val2) == 2) {
        strcpy(from_to_array[val1], val2);
        if (val1 > max_index)
            max_index = val1;
    }

    fclose(fp);

    return max_index;
}

// create output .h file
void create_h(char *path, char *from, char *to) {
    FILE *fp = fopen(path, "w");

    // write comments and function prototype
    fprintf(fp, "// %s\n", strstr(path, CSV_PATH));
    fprintf(fp, "// translate %s to %s - generated from csv\n\n", from, to);
    fprintf(fp, "// get %s from %s\n", to, from);
    fprintf(fp, "// params:\n");
    fprintf(fp, "//      - %s - %s to translate from\n", from, from);
    fprintf(fp, "// returns:\n");
    fprintf(fp, "//      %s corresponding to %s\n", to, from);
    fprintf(fp, "extern const char *get_%s_from_%s(int %s);", to, from, from);

    fclose(fp);
}

// create output .c file
void create_c(
    char *path,
    char *h_path,
    char *from,
    char *to,
    char from_to_array[][BUFFER_SIZE],
    size_t max_index
) {
    FILE *fp = fopen(path, "w");

    char arr_name[BUFFER_SIZE], arr_len_name[BUFFER_SIZE];
    sprintf(arr_name, "%s_to_%s", from, to);
    sprintf(arr_len_name, "%s_to_%s_len", from, to);

    // write includes and the beginning of array
    fprintf(fp, "#include \"%s\"\n\n", strstr(h_path, CSV_PATH));
    fprintf(fp, "#include <stdio.h>\n\n");
    fprintf(fp, "static const char *%s[] = {\n", arr_name);

    // write values
    for (size_t i = 0; i <= max_index; i++) {
        if (strlen(from_to_array[i]) > 0)
            fprintf(fp, "    \"%s\",\n", from_to_array[i]);
        else
            fprintf(fp, "    \"%zu\",\n", i);
    }

    // write the end of array and len
    fprintf(fp, "};\n");
    fprintf(fp, "int %s = %zu;\n\n", arr_len_name, max_index + 1);

    // write the getter
    fprintf(fp, "const char *get_%s_from_%s(int %s) {\n", to, from, from);
    fprintf(fp, "    if (%s >= 0 && %s < %s)\n", from, from, arr_len_name);
    fprintf(fp, "        return %s[%s];\n", arr_name, from);
    fprintf(
        fp,
        "    fprintf(stderr, \"%s = %%d is outside of table range [0; %%d]\\n\", %s, %s - 1);\n",
        from,
        from,
        arr_len_name
    );
    fprintf(fp, "    return \"null\";\n");
    fprintf(fp, "}");

    fclose(fp);
}

void create_table(char *file_name) {
    // read from input file
    char input_path[PATH_MAX];
    sprintf(input_path, "%s/%s", CSV_PATH, file_name);
    char from[BUFFER_SIZE], to[BUFFER_SIZE];
    char from_to_array[MAX_ARR_SIZE][BUFFER_SIZE] = {0};
    size_t max_index = read_csv(input_path, from, to, from_to_array);

    // create output .h file
    char h_path[PATH_MAX];
    sprintf(h_path, "%s/%s_to_%s.h", OUT_PATH, from, to);
    create_h(h_path, from, to);

    // create output .c file
    char c_path[PATH_MAX];
    sprintf(c_path, "%s/%s_to_%s.c", OUT_PATH, from, to);
    create_c(c_path, h_path, from, to, from_to_array, max_index);
}

int main() {
    // make directory for output files
    mkdir(OUT_PATH, 0755);

    DIR *csv_dir = opendir(CSV_PATH);
    struct dirent *entry;
    while ((entry = readdir(csv_dir))) {
        char *file_name = entry->d_name;
        size_t file_name_len = strlen(file_name);
        // create lookup tables for each *.csv file
        if (file_name_len > EXT_LEN && !strcmp(file_name + file_name_len - EXT_LEN, EXT))
            create_table(entry->d_name);
    }
    closedir(csv_dir);

    return 0;
}