+static int ps_name_cmp(const void *p1, const void *p2)
+{
+ const struct parsed_struct *ps1 = p1, *ps2 = p2;
+ return strcmp(ps1->name, ps2->name);
+}
+
+// parsed struct cache
+static struct parsed_struct *ps_cache;
+static int ps_cache_size;
+static int ps_cache_alloc;
+
+static int struct_handler(FILE *fhdr, char *proto, int *line)
+{
+ struct parsed_struct *ps;
+ char lstr[256], *p;
+ int offset = 0;
+ int m = 0;
+ int ret;
+
+ if (ps_cache_size >= ps_cache_alloc) {
+ ps_cache_alloc = ps_cache_alloc * 2 + 64;
+ ps_cache = realloc(ps_cache, ps_cache_alloc
+ * sizeof(ps_cache[0]));
+ my_assert_not(ps_cache, NULL);
+ memset(ps_cache + ps_cache_size, 0,
+ (ps_cache_alloc - ps_cache_size)
+ * sizeof(ps_cache[0]));
+ }
+
+ ps = &ps_cache[ps_cache_size++];
+ ret = sscanf(proto, "struct %255s {", ps->name);
+ if (ret != 1) {
+ printf("%s:%d: struct parse failed\n", hdrfn, *line);
+ return -1;
+ }
+
+ while (fgets(lstr, sizeof(lstr), fhdr))
+ {
+ (*line)++;
+
+ p = sskip(lstr);
+ if (p[0] == '/' && p[1] == '/')
+ continue;
+ if (p[0] == '}')
+ break;
+
+ if (m >= ARRAY_SIZE(ps->members)) {
+ printf("%s:%d: too many struct members\n",
+ hdrfn, *line);
+ return -1;
+ }
+
+ hdrfline = *line;
+ ret = parse_protostr(p, &ps->members[m].pp);
+ if (ret < 0) {
+ printf("%s:%d: struct member #%d/%02x "
+ "doesn't parse\n", hdrfn, *line,
+ m, offset);
+ return -1;
+ }
+ ps->members[m].offset = offset;
+ offset += 4;
+ m++;
+ }
+
+ ps->member_count = m;
+
+ return 0;
+}
+
+// parsed proto cache