+ 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
+static struct parsed_proto *pp_cache;
+static int pp_cache_size;
+static int pp_cache_alloc;
+
+static int b_pp_c_handler(char *proto, const char *fname,
+ int is_include, int is_osinc, int is_cinc)
+{
+ int ret;
+
+ if (pp_cache_size >= pp_cache_alloc) {
+ pp_cache_alloc = pp_cache_alloc * 2 + 64;
+ pp_cache = realloc(pp_cache, pp_cache_alloc
+ * sizeof(pp_cache[0]));
+ my_assert_not(pp_cache, NULL);
+ memset(pp_cache + pp_cache_size, 0,
+ (pp_cache_alloc - pp_cache_size)
+ * sizeof(pp_cache[0]));
+ }
+
+ ret = parse_protostr(proto, &pp_cache[pp_cache_size]);
+ if (ret < 0)
+ return -1;
+
+ pp_cache[pp_cache_size].is_include = is_include;
+ pp_cache[pp_cache_size].is_osinc = is_osinc;
+ pp_cache[pp_cache_size].is_cinc = is_cinc;
+ pp_cache_size++;
+ return 0;
+}
+
+static void build_caches(FILE *fhdr)
+{
+ long pos;
+ int ret;
+
+ pos = ftell(fhdr);
+ rewind(fhdr);
+
+ ret = do_protostrs(fhdr, hdrfn, 0);
+ if (ret < 0)
+ exit(1);
+
+ qsort(pp_cache, pp_cache_size, sizeof(pp_cache[0]), pp_name_cmp);
+ qsort(ps_cache, ps_cache_size, sizeof(ps_cache[0]), ps_name_cmp);
+ fseek(fhdr, pos, SEEK_SET);
+}
+
+static const struct parsed_proto *proto_parse(FILE *fhdr, const char *sym,
+ int quiet)
+{
+ const struct parsed_proto *pp_ret;
+ struct parsed_proto pp_search;
+ char *p;
+
+ if (pp_cache == NULL)
+ build_caches(fhdr);
+
+ if (sym[0] == '_') // && strncmp(fname, "stdc", 4) == 0)
+ sym++;
+
+ strcpy(pp_search.name, sym);
+ p = strchr(pp_search.name, '@');
+ if (p != NULL)
+ *p = 0;
+
+ pp_ret = bsearch(&pp_search, pp_cache, pp_cache_size,
+ sizeof(pp_cache[0]), pp_name_cmp);
+ if (pp_ret == NULL && !quiet)