summaryrefslogtreecommitdiff
path: root/gen_inl.c
blob: 116c5f599a0fa7f11cc04a8769df871c76ab7f70 (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
#if 0
gcc -fsanitize=address,undefined,leak gen_inl.c -o gen_inl && ./gen_inl
exit
#endif

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char const *const SOURCES[] = {
  "./source/kit/status.h",        "./source/kit/allocator.h",
  "./source/kit/array_ref.h",     "./source/kit/dynamic_array.h",
  "./source/kit/string_ref.h",    "./source/kit/file.h",
  "./source/kit/allocator.c",     "./source/kit/array_ref.c",
  "./source/kit/dynamic_array.c", "./source/kit/file.c"
};

char const *repeat(int n, char c) {
  static char buf[200];
  for (int i = 0; i < n && i < 199; i++) buf[i] = c;
  buf[n] = '\0';
  return buf;
}

int skip_whitespaces(char const *const line, int i) {
  while (line[i] == ' ') i++;
  return i;
}

int skip(char const *const line, int i, char const *const s) {
  int j = 0;
  while (s[j] != '\0') {
    if (line[i] != s[j])
      return -1;
    i++;
    j++;
  }
  return i;
}

int is_local_include(char const *const line) {
  if (line[0] != '#')
    return 0;
  int i = skip_whitespaces(line, 1);
  i     = skip(line, i, "include");
  if (i == -1)
    return 0;
  i = skip_whitespaces(line, i);
  if (line[i] != '"')
    return 0;
  return 1;
}

int is_empty_line(char const *const line) {
  int i = skip_whitespaces(line, 0);
  return line[i] == '\0' || line[i] == '\n';
}

int write_file(FILE *out, char const *const source) {
  assert(out != NULL);
  assert(source != NULL);

  FILE *in = fopen(source, "rt");

  if (in == NULL) {
    fprintf(stderr, "File not found: %s\n", source);
    return 1;
  }

  fprintf(out, "/*%s*\n", repeat(67, '*'));
  fprintf(out, " *%s*\n", repeat(67, ' '));
  fprintf(out, " *    File:   %s%s*\n", source,
          repeat(55 - strlen(source), ' '));
  fprintf(out, " *%s*\n", repeat(67, ' '));
  fprintf(out, " *%s*/\n", repeat(67, '*'));

  char line[200];
  char buf[400];

  while (fgets(line, 199, in) != NULL) {
    if (is_empty_line(line) || is_local_include(line))
      continue;

    int j = 0;
    for (int i = 0; line[i] != '\0'; i++) {
      if (line[i] == '\t') {
        buf[j++] = ' ';
        buf[j++] = ' ';
      } else if (line[i] != '\n' && line[i] != '\r')
        buf[j++] = line[i];
    }
    buf[j] = '\0';
    fprintf(out, "%s\n", buf);
  }

  fclose(in);
  return 0;
}

int main(int argc, char **argv) {
  char const *const out_file = "./include/kit.inl.h";
  FILE             *out      = fopen(out_file, "wt");
  if (out == NULL) {
    fprintf(stderr, "Can't write: %s\n", out_file);
    return 1;
  }

  fprintf(out, "#ifndef KIT_INL_H\n");
  fprintf(out, "#define KIT_INL_H\n");

  for (int i = 0; i < sizeof SOURCES / sizeof *SOURCES; i++)
    if (write_file(out, SOURCES[i]) != 0) {
      fclose(out);
      return 1;
    }

  fprintf(out, "#endif\n");

  fclose(out);
  return 0;
}