+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);
+
+ // ugh...
+ if (sym[0] == '_' && !IS_START(sym, "__W"))
+ 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)