genids.c 3.75 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char **unique_ids;
int unique_ids_size;
int unique_ids_maxsize;

11 12
int cmp(const void *p1, const void *p2) {
  return strcmp(*(char *const *)p1, *(char *const *)p2);
13 14 15
}

/* return 1 if s was not already known, 0 if it was */
16
int new_unique_id(char *s, char *input_file) {
17
  if (unique_ids_size)
18 19 20 21 22
    if (bsearch(&s, unique_ids, unique_ids_size, sizeof(char *), cmp) != NULL) {
      printf("error: ID %s is not unique in %s\n", s, input_file);
      return 0;
    }

23 24 25
  if (unique_ids_size == unique_ids_maxsize) {
    unique_ids_maxsize += 256;
    unique_ids = realloc(unique_ids, unique_ids_maxsize * sizeof(char *));
26 27 28 29 30

    if (unique_ids == NULL) {
      printf("error: out of memory\n");
      abort();
    }
31
  }
32

33
  unique_ids[unique_ids_size] = strdup(s);
34 35 36 37 38 39

  if (unique_ids[unique_ids_size] == NULL) {
    printf("error: out of memory\n");
    abort();
  }

40 41 42 43 44 45 46 47 48
  unique_ids_size++;
  qsort(unique_ids, unique_ids_size, sizeof(char *), cmp);
  return 1;
}

char *bufname;
int bufname_size;
int bufname_maxsize;

49
void putname(int c) {
50 51 52
  if (bufname_size == bufname_maxsize) {
    bufname_maxsize += 256;
    bufname = realloc(bufname, bufname_maxsize);
53 54 55 56 57

    if (bufname == NULL) {
      printf("error: memory allocation error\n");
      exit(1);
    }
58
  }
59

60 61 62 63 64 65 66 67
  bufname[bufname_size] = c;
  bufname_size++;
}

char *bufvalue;
int bufvalue_size;
int bufvalue_maxsize;

68
void putvalue(int c) {
69 70 71
  if (bufvalue_size == bufvalue_maxsize) {
    bufvalue_maxsize += 256;
    bufvalue = realloc(bufvalue, bufvalue_maxsize);
72 73 74 75 76

    if (bufvalue == NULL) {
      printf("error: memory allocation error\n");
      exit(1);
    }
77
  }
78

79 80 81 82
  bufvalue[bufvalue_size] = c;
  bufvalue_size++;
}

83
void smash_spaces(FILE *f) {
84
  int c;
85

86 87
  while (1) {
    c = fgetc(f);
88

89
    if (isspace(c)) continue;
90

91
    if (c == ' ') continue;
92

93
    if (c == '\t') continue;
94

95
    if (c == '\n') continue;
96

97
    if (c == 10 || c == 13) continue;
98

99 100 101
    if (c == '#') {
      while (1) {
        c = fgetc(f);
102

103 104
        if (c == '\n' || c == EOF) break;
      }
105

106 107
      continue;
    }
108

109 110
    break;
  }
111

112 113 114
  if (c != EOF) ungetc(c, f);
}

115
void get_line(FILE *f, char **name, char **value) {
116 117 118 119 120 121 122
  int c;
  bufname_size = 0;
  bufvalue_size = 0;
  *name = NULL;
  *value = NULL;
  smash_spaces(f);
  c = fgetc(f);
123 124 125 126 127 128

  while (!(c == '=' || isspace(c) || c == EOF)) {
    putname(c);
    c = fgetc(f);
  }

129
  if (c == EOF) return;
130

131
  putname(0);
132

133
  while (!(c == EOF || c == '=')) c = fgetc(f);
134

135
  if (c == EOF) return;
136

137 138
  smash_spaces(f);
  c = fgetc(f);
139 140 141 142 143 144

  while (!(c == 10 || c == 13 || c == EOF)) {
    putvalue(c);
    c = fgetc(f);
  }

145
  putvalue(0);
146

147
  if (bufname_size <= 1) return;
148

149
  if (bufvalue_size <= 1) return;
150

151 152 153 154
  *name = bufname;
  *value = bufvalue;
}

155
int main(int n, char **v) {
156 157 158 159 160 161 162
  FILE *in;
  FILE *out;
  char *name;
  char *value;
  char *in_name;
  char *out_name;

163 164 165 166
  if (n != 3) {
    printf("error: gimme <source> <dest>\n");
    exit(1);
  }
167 168 169 170

  n = 0;
  in_name = v[1];
  out_name = v[2];
171 172 173 174 175 176
  in = fopen(in_name, "r");

  if (in == NULL) {
    perror(in_name);
    exit(1);
  }
177

178 179 180 181 182 183
  out = fopen(out_name, "w");

  if (out == NULL) {
    perror(out_name);
    exit(1);
  }
184 185 186 187 188

  fprintf(out, "/* generated file, do not edit by hand */\n\n");

  while (1) {
    get_line(in, &name, &value);
189

190
    if (name == NULL) break;
191

192
    if (isspace(value[strlen(value)-1])) {
Cedric Roux's avatar
Cedric Roux committed
193
      printf("error: bad value '%s' (no space at the end please!)\n", value);
194 195 196
      unlink(out_name);
      exit(1);
    }
197

198
    if (!strcmp(name, "ID")) {
199 200 201 202 203
      if (!new_unique_id(value, in_name)) {
        unlink(out_name);
        exit(1);
      }

204 205 206 207 208
      fprintf(out, "#define T_%s T_ID(%d)\n", value, n);
      n++;
    }
  }

209
  fprintf(out, "#define T_NUMBER_OF_IDS %d\n", n);
210 211 212 213
  fclose(in);
  fclose(out);
  return 0;
}