1ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata/*
2ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * This file is part of ltrace.
3e56fe644f725f2c1c8308e7c2b5f9cd02e89eed0Petr Machata * Copyright (C) 2012,2013 Petr Machata, Red Hat Inc.
4ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata *
5ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * This program is free software; you can redistribute it and/or
6ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * modify it under the terms of the GNU General Public License as
7ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * published by the Free Software Foundation; either version 2 of the
8ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * License, or (at your option) any later version.
9ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata *
10ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * This program is distributed in the hope that it will be useful, but
11ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of
12ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * General Public License for more details.
14ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata *
15ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * You should have received a copy of the GNU General Public License
16ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * along with this program; if not, write to the Free Software
17ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata * 02110-1301 USA
19ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata */
20ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
2182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata#include <alloca.h>
22f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata#include <errno.h>
23ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include <stdlib.h>
24ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include <string.h>
2582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata#include <stdio.h>
26ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
27b1ab2aefa199ea8e14e29bac78ae71030c2d4863Petr Machata#include "common.h"
28ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include "callback.h"
29ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include "param.h"
30f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata#include "prototype.h"
31ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata#include "type.h"
3282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata#include "options.h"
3382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata#include "read_config_file.h"
3482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata#include "backend.h"
35ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
3608cdf328add7b723b94b151866e5d0173662f6c6Petr Machatastruct protolib_cache g_protocache;
3708cdf328add7b723b94b151866e5d0173662f6c6Petr Machatastatic struct protolib legacy_typedefs;
38ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
39ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatavoid
40ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_init(struct prototype *proto)
41ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
42ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	VECT_INIT(&proto->params, struct param);
43ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
44ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	proto->return_info = NULL;
45ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	proto->own_return_info = 0;
46ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
47ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
48ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic void
49ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataparam_destroy_cb(struct param *param, void *data)
50ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
51ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	param_destroy(param);
52ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
53ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
54ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatavoid
55ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_destroy(struct prototype *proto)
56ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
57ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	if (proto == NULL)
58ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return;
59ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	if (proto->own_return_info) {
60ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		type_destroy(proto->return_info);
61ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		free(proto->return_info);
62ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	}
63ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
64ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	VECT_DESTROY(&proto->params, struct param, &param_destroy_cb, NULL);
65ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
66ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
67ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataint
68ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_push_param(struct prototype *proto, struct param *param)
69ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
70ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return VECT_PUSHBACK(&proto->params, param);
71ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
72ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
73ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatasize_t
74ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_num_params(struct prototype *proto)
75ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
76ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return vect_size(&proto->params);
77ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
78ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
79ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatavoid
80ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_destroy_nth_param(struct prototype *proto, size_t n)
81ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
82ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	assert(n < prototype_num_params(proto));
83ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	VECT_ERASE(&proto->params, struct param, n, n+1,
84ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		   &param_destroy_cb, NULL);
85ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
86ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
87ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastruct param *
88ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_get_nth_param(struct prototype *proto, size_t n)
89ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
90ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	assert(n < prototype_num_params(proto));
91ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return VECT_ELEMENT(&proto->params, struct param, n);
92ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
93ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
94ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastruct each_param_data {
95ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct prototype *proto;
96ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	enum callback_status (*cb)(struct prototype *, struct param *, void *);
97ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	void *data;
98ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata};
99ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
100ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic enum callback_status
101ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataeach_param_cb(struct param *param, void *data)
102ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
103ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct each_param_data *cb_data = data;
104ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return (cb_data->cb)(cb_data->proto, param, cb_data->data);
105ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
106ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
107ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastruct param *
108ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprototype_each_param(struct prototype *proto, struct param *start_after,
109ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		     enum callback_status (*cb)(struct prototype *,
110ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata						struct param *, void *),
111ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		     void *data)
112ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
113ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct each_param_data cb_data = { proto, cb, data };
114ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return VECT_EACH(&proto->params, struct param, start_after,
115ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata			 &each_param_cb, &cb_data);
116ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
117ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
118ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatavoid
1193ac9b91974678878889776221c390f39f5c2ffcfPetr Machatanamed_type_init(struct named_type *named,
1203ac9b91974678878889776221c390f39f5c2ffcfPetr Machata		struct arg_type_info *info, int own_type)
1213ac9b91974678878889776221c390f39f5c2ffcfPetr Machata{
1223ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	named->info = info;
1233ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	named->own_type = own_type;
1243ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	named->forward = 0;
1253ac9b91974678878889776221c390f39f5c2ffcfPetr Machata}
1263ac9b91974678878889776221c390f39f5c2ffcfPetr Machata
1273ac9b91974678878889776221c390f39f5c2ffcfPetr Machatavoid
128ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatanamed_type_destroy(struct named_type *named)
129ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
1303ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	if (named->own_type) {
131ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		type_destroy(named->info);
132ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		free(named->info);
133ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	}
134ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
135ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
136f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machatavoid
137ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprotolib_init(struct protolib *plib)
138ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
13997485501f87e5452bc49721003ebfb9717f497b6Peter Wu	DICT_INIT(&plib->prototypes, char *, struct prototype,
140f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		  dict_hash_string, dict_eq_string, NULL);
141ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
14297485501f87e5452bc49721003ebfb9717f497b6Peter Wu	DICT_INIT(&plib->named_types, char *, struct named_type,
143f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		  dict_hash_string, dict_eq_string, NULL);
144ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
145ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	VECT_INIT(&plib->imports, struct protolib *);
1467f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata
1477f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata	plib->refs = 0;
148ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
149ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
150ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic void
151f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machatadestroy_prototype_cb(struct prototype *proto, void *data)
152ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
153ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	prototype_destroy(proto);
154ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
155ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
156ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic void
157f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machatadestroy_named_type_cb(struct named_type *named, void *data)
158ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
159ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	named_type_destroy(named);
160ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
161ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
162ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatavoid
163ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprotolib_destroy(struct protolib *plib)
164ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
1657f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata	assert(plib->refs == 0);
1667f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata
167ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	VECT_DESTROY(&plib->imports, struct prototype *, NULL, NULL);
168ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
169f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	DICT_DESTROY(&plib->prototypes, const char *, struct prototype,
170f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		     dict_dtor_string, destroy_prototype_cb, NULL);
171ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
172f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	DICT_DESTROY(&plib->named_types, const char *, struct named_type,
173f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		     dict_dtor_string, destroy_named_type_cb, NULL);
174ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
175ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
176ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic struct protolib **
177ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataeach_import(struct protolib *plib, struct protolib **start_after,
178ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	    enum callback_status (*cb)(struct protolib **, void *), void *data)
179ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
18082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
181ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return VECT_EACH(&plib->imports, struct protolib *,
182ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata			 start_after, cb, data);
183ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
184ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
185ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic enum callback_status
186ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatais_or_imports(struct protolib **plibp, void *data)
187ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
18882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plibp != NULL);
18982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(*plibp != NULL);
190ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct protolib *import = data;
191ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	if (*plibp == import
192ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	    || each_import(*plibp, NULL, &is_or_imports, import) != NULL)
193ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return CBS_STOP;
194ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	else
195ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return CBS_CONT;
196ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
197ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
198ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataint
199ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprotolib_add_import(struct protolib *plib, struct protolib *import)
200ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
20182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
20282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(import != NULL);
20382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (is_or_imports(&import, plib) == CBS_STOP) {
20482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		fprintf(stderr, "Recursive import rejected.\n");
205ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return -2;
20682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
207ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
20882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return VECT_PUSHBACK(&plib->imports, &import) < 0 ? -1 : 0;
209ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
210ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
211ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic int
212f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machatabailout(const char *name, int own)
213f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata{
214f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	int save_errno = errno;
215f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	if (own)
216f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		free((char *)name);
217f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	errno = save_errno;
218f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	return -1;
219f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata}
220f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata
221ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataint
222ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprotolib_add_prototype(struct protolib *plib, const char *name, int own_name,
223ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		       struct prototype *proto)
224ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
22582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
226b1ab2aefa199ea8e14e29bac78ae71030c2d4863Petr Machata	if (strdup_if(&name, name, !own_name) < 0)
227f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		return -1;
228f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	if (DICT_INSERT(&plib->prototypes, &name, proto) < 0)
229f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		return bailout(name, own_name);
230f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	return 0;
231ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
232ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
233ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataint
234ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machataprotolib_add_named_type(struct protolib *plib, const char *name, int own_name,
235ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata			struct named_type *named)
236ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
23782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
238b1ab2aefa199ea8e14e29bac78ae71030c2d4863Petr Machata	if (strdup_if(&name, name, !own_name) < 0)
239f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		return -1;
240f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	if (DICT_INSERT(&plib->named_types, &name, named) < 0)
241f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata		return bailout(name, own_name);
242f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	return 0;
243ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
244ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
245ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastruct lookup {
246ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	const char *name;
2473ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	struct dict *(*getter)(struct protolib *plib);
24882f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	bool imports;
24982f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	void *result;
250ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata};
251ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
2523ac9b91974678878889776221c390f39f5c2ffcfPetr Machatastatic struct dict *
2533ac9b91974678878889776221c390f39f5c2ffcfPetr Machataget_prototypes(struct protolib *plib)
2543ac9b91974678878889776221c390f39f5c2ffcfPetr Machata{
25582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
256f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	return &plib->prototypes;
2573ac9b91974678878889776221c390f39f5c2ffcfPetr Machata}
2583ac9b91974678878889776221c390f39f5c2ffcfPetr Machata
2593ac9b91974678878889776221c390f39f5c2ffcfPetr Machatastatic struct dict *
2603ac9b91974678878889776221c390f39f5c2ffcfPetr Machataget_named_types(struct protolib *plib)
2613ac9b91974678878889776221c390f39f5c2ffcfPetr Machata{
26282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
263f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	return &plib->named_types;
2643ac9b91974678878889776221c390f39f5c2ffcfPetr Machata}
2653ac9b91974678878889776221c390f39f5c2ffcfPetr Machata
266ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastatic enum callback_status
2673ac9b91974678878889776221c390f39f5c2ffcfPetr Machataprotolib_lookup_rec(struct protolib **plibp, void *data)
268ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
26982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plibp != NULL);
27082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(*plibp != NULL);
271ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	struct lookup *lookup = data;
2723ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	struct dict *dict = (*lookup->getter)(*plibp);
273ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
274f7650d1e1c09e360a0cd27ee99b051cc9b127091Petr Machata	lookup->result = dict_find(dict, &lookup->name);
275ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	if (lookup->result != NULL)
276ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return CBS_STOP;
277ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
27882f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	if (lookup->imports && each_import(*plibp, NULL, &protolib_lookup_rec,
27982f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata					   lookup) != NULL) {
280ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		assert(lookup->result != NULL);
281ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		return CBS_STOP;
282ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	}
283ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
284ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return CBS_CONT;
285ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
286ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
2873ac9b91974678878889776221c390f39f5c2ffcfPetr Machatastatic void *
2883ac9b91974678878889776221c390f39f5c2ffcfPetr Machataprotolib_lookup(struct protolib *plib, const char *name,
28982f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata		struct dict *(*getter)(struct protolib *),
29082f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata		bool imports)
291ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata{
29282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
29382f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	struct lookup lookup = { name, getter, imports, NULL };
2943ac9b91974678878889776221c390f39f5c2ffcfPetr Machata	if (protolib_lookup_rec(&plib, &lookup) == CBS_STOP)
295ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		assert(lookup.result != NULL);
296ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	else
297ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata		assert(lookup.result == NULL);
298ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata	return lookup.result;
299ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata}
300ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machata
3013ac9b91974678878889776221c390f39f5c2ffcfPetr Machatastruct prototype *
30282f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machataprotolib_lookup_prototype(struct protolib *plib, const char *name, bool imports)
3033ac9b91974678878889776221c390f39f5c2ffcfPetr Machata{
30482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
30582f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	return protolib_lookup(plib, name, &get_prototypes, imports);
3063ac9b91974678878889776221c390f39f5c2ffcfPetr Machata}
3073ac9b91974678878889776221c390f39f5c2ffcfPetr Machata
308ebc56a70e20ca0b3fc49c0eb5fc83e56c5e1fa5bPetr Machatastruct named_type *
30982f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machataprotolib_lookup_type(struct protolib *plib, const char *name, bool imports)
3103ac9b91974678878889776221c390f39f5c2ffcfPetr Machata{
31182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plib != NULL);
31282f748d1bc2b95d594327ad15f3a6908070dd5c3Petr Machata	return protolib_lookup(plib, name, &get_named_types, imports);
3133ac9b91974678878889776221c390f39f5c2ffcfPetr Machata}
31482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
31582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic void
31682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatadestroy_protolib_cb(struct protolib **plibp, void *data)
31782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
31882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	assert(plibp != NULL);
3197f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata
320e56fe644f725f2c1c8308e7c2b5f9cd02e89eed0Petr Machata	if (*plibp != NULL
321e56fe644f725f2c1c8308e7c2b5f9cd02e89eed0Petr Machata	    && --(*plibp)->refs == 0) {
3227f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata		protolib_destroy(*plibp);
3237f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata		free(*plibp);
3247f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata	}
32582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
32682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
32782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatavoid
32882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataprotolib_cache_destroy(struct protolib_cache *cache)
32982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
33082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	DICT_DESTROY(&cache->protolibs, const char *, struct protolib *,
33182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		     dict_dtor_string, destroy_protolib_cb, NULL);
33282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
33382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
33482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastruct load_config_data {
33582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct protolib_cache *self;
33682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	const char *key;
33782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct protolib *result;
33882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata};
33982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
34082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic struct protolib *
34182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataconsider_config_dir(struct protolib_cache *cache,
34282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		    const char *path, const char *key)
34382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
34482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	size_t len = sizeof ".conf";
34582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	char *buf = alloca(strlen(path) + 1 + strlen(key) + len);
346b5c837f545342b6017fe6ec7aa60c1fc866fde06Petr Machata	sprintf(buf, "%s/%s.conf", path, key);
34782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
348a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	return protolib_cache_file(cache, buf, 0);
34982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
35082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
35182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic enum callback_status
35282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataconsider_confdir_cb(struct opt_F_t *entry, void *d)
35382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
35482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (opt_F_get_kind(entry) != OPT_F_DIR)
35582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return CBS_CONT;
35682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct load_config_data *data = d;
35782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
35882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	data->result = consider_config_dir(data->self,
35982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata					   entry->pathname, data->key);
36082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return data->result != NULL ? CBS_STOP : CBS_CONT;
36182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
36282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
36382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic int
36482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataload_dash_F_dirs(struct protolib_cache *cache,
36582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		 const char *key, struct protolib **retp)
36682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
36782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct load_config_data data = {cache, key};
36882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
36982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (VECT_EACH(&opt_F, struct opt_F_t, NULL,
37082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		      consider_confdir_cb, &data) == NULL)
37182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		/* Not found.  That's fine.  */
37282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return 0;
37382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
37482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (data.result == NULL)
37582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		/* There were errors.  */
37682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return -1;
37782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
37882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	*retp = data.result;
37982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return 0;
38082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
38182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
38282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic int
38382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataload_config(struct protolib_cache *cache,
38482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    const char *key, int private, struct protolib **retp)
38582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
38682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	const char **dirs = NULL;
38782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (os_get_config_dirs(private, &dirs) < 0
38882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    || dirs == NULL)
38982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return -1;
39082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
39182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	for (; *dirs != NULL; ++dirs) {
39282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		struct protolib *plib = consider_config_dir(cache, *dirs, key);
39382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		if (plib != NULL) {
39482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			*retp = plib;
39582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			break;
39682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		}
39782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
39882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
39982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return 0;
40082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
40182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
402aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machatastatic enum callback_status
403aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machataimport_legacy_file(char **fnp, void *data)
404aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata{
405aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	struct protolib_cache *cache = data;
406aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	struct protolib *plib = protolib_cache_file(cache, *fnp, 1);
407aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	if (plib != NULL) {
408aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		/* The cache now owns the file name.  */
409aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		*fnp = NULL;
410aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		if (protolib_add_import(&cache->imports, plib) < 0)
411aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata			return CBS_STOP;
412aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	}
413aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
414aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	return CBS_CONT;
415aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata}
416aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata
4174c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machatastatic int
4184c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machataadd_ltrace_conf(struct protolib_cache *cache)
4194c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata{
4204c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata	/* Look into private config directories for .ltrace.conf and
4214c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata	 * into system config directories for ltrace.conf.  If it's
4224c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata	 * found, add it to implicit import module.  */
423aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	struct vect legacy_files;
424aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	VECT_INIT(&legacy_files, char *);
425aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	if (os_get_ltrace_conf_filenames(&legacy_files) < 0) {
426aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata		vect_destroy(&legacy_files, NULL, NULL);
4274c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata		return -1;
428aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	}
4294c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata
430aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	int ret = VECT_EACH(&legacy_files, char *, NULL,
431aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata			    import_legacy_file, cache) == NULL ? 0 : -1;
432aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	VECT_DESTROY(&legacy_files, char *, vect_dtor_string, NULL);
433aa3db6b1234da0e542ba7782849cf200d0d91c1cPetr Machata	return ret;
4344c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata}
4354c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata
43682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic enum callback_status
43782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataadd_imports_cb(struct opt_F_t *entry, void *data)
43882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
43982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct protolib_cache *self = data;
44082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (opt_F_get_kind(entry) != OPT_F_FILE)
44182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return CBS_CONT;
44282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
44382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct protolib *new_import
444a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		= protolib_cache_file(self, entry->pathname, 0);
44582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
44682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (new_import == NULL
44782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    || protolib_add_import(&self->imports, new_import) < 0)
44882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		/* N.B. If new_import is non-NULL, it has been already
44982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		 * cached.  We don't therefore destroy it on
45082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		 * failures.  */
45182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return CBS_STOP;
45282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
45382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return CBS_CONT;
45482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
45582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
45682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataint
45782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataprotolib_cache_init(struct protolib_cache *cache, struct protolib *import)
45882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
45997485501f87e5452bc49721003ebfb9717f497b6Peter Wu	DICT_INIT(&cache->protolibs, char *, struct protolib *,
46082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		  dict_hash_string, dict_eq_string, NULL);
46182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	protolib_init(&cache->imports);
46282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
46382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	/* At this point the cache is consistent.  This is important,
46482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * because next we will use it to cache files that we load
46582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * due to -F.
46682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 *
46782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * But we are about to construct the implicit import module,
46882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * which means this module can't be itself imported to the
46982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * files that we load now.  So remember that we are still
47082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * bootstrapping.  */
47182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	cache->bootstrap = 1;
47282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
47382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (protolib_add_import(&cache->imports, &legacy_typedefs) < 0
47482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    || (import != NULL
47582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		&& protolib_add_import(&cache->imports, import) < 0)
4764c4e4012db96aee7ef236c0684690842fb6a3e47Petr Machata	    || add_ltrace_conf(cache) < 0
47782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    || VECT_EACH(&opt_F, struct opt_F_t, NULL,
47882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			 add_imports_cb, cache) != NULL) {
47982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		protolib_cache_destroy(cache);
48082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return -1;
48182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
48282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
48382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	cache->bootstrap = 0;
48482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return 0;
48582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
48682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
48782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic enum callback_status
48882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataadd_import_cb(struct protolib **importp, void *data)
48982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
49082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct protolib *plib = data;
49182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (protolib_add_import(plib, *importp) < 0)
49282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return CBS_STOP;
49382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	else
49482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return CBS_CONT;
49582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
49682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
49782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic struct protolib *
49882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatabuild_default_config(struct protolib_cache *cache, const char *key)
49982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
50082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	struct protolib *new_plib = malloc(sizeof(*new_plib));
50182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (new_plib == NULL) {
50282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		fprintf(stderr, "Couldn't create config module %s: %s\n",
50382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			key, strerror(errno));
50482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return NULL;
50582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
50682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
50782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	protolib_init(new_plib);
50882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
50982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	/* If bootstrapping, copy over imports from implicit import
51082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * module to new_plib.  We can't reference the implicit
51182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * import module itself, because new_plib will become part of
51282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * this same implicit import module itself.  */
51382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if ((cache->bootstrap && each_import(&cache->imports, NULL,
51482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata					     add_import_cb, new_plib) != NULL)
51582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    || (!cache->bootstrap
51682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		&& protolib_add_import(new_plib, &cache->imports) < 0)) {
51782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
51882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		fprintf(stderr,
51982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			"Couldn't add imports to config module %s: %s\n",
52082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			key, strerror(errno));
52182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		protolib_destroy(new_plib);
52282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		free(new_plib);
52382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return NULL;
52482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
52582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
52682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return new_plib;
52782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
52882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
52982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastatic void
53082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataattempt_to_cache(struct protolib_cache *cache,
53182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		 const char *key, struct protolib *plib)
53282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
533a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	if (protolib_cache_protolib(cache, key, 1, plib) == 0
53482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	    || plib == NULL)
53582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		/* Never mind failing to store a NULL.  */
53682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return;
53782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
53882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	/* Returning a protolib that hasn't been cached would leak
53982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * that protolib, but perhaps it's less bad then giving up
54082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	 * outright.  At least print an error message.  */
54182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	fprintf(stderr, "Couldn't cache prototype library for %s\n", key);
54298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	free((void *) key);
54382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
54482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
54598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machataint
54698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machataprotolib_cache_maybe_load(struct protolib_cache *cache,
54798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			  const char *key, int own_key, bool allow_private,
54898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			  struct protolib **retp)
54982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
55098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (DICT_FIND_VAL(&cache->protolibs, &key, retp) == 0)
55198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return 0;
55282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
553b1ab2aefa199ea8e14e29bac78ae71030c2d4863Petr Machata	if (strdup_if(&key, key, !own_key) < 0) {
554a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		fprintf(stderr, "Couldn't cache %s: %s\n",
555a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			key, strerror(errno));
55698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return -1;
557a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	}
558a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata
55998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	*retp = NULL;
56098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (load_dash_F_dirs(cache, key, retp) < 0
56198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	    || (*retp == NULL && allow_private
56298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		&& load_config(cache, key, 1, retp) < 0)
56398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	    || (*retp == NULL
56498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		&& load_config(cache, key, 0, retp) < 0))
56598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	{
56682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		fprintf(stderr,
56782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			"Error occurred when attempting to load a prototype "
56882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			"library for %s.\n", key);
569d2154eae286064c4114ec924186535961dfaad79Petr Machata		if (!own_key)
570d2154eae286064c4114ec924186535961dfaad79Petr Machata			free((void *) key);
57198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return -1;
57298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	}
57382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
57498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (*retp != NULL)
57598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		attempt_to_cache(cache, key, *retp);
57698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	else if (!own_key)
57798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		free((void *) key);
57898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
57998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	return 0;
58098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata}
58198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
58298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machatastruct protolib *
58398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machataprotolib_cache_load(struct protolib_cache *cache,
58498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		    const char *key, int own_key, bool allow_private)
58598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata{
58698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	struct protolib *plib;
58798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (protolib_cache_maybe_load(cache, key, own_key,
58898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata				      allow_private, &plib) < 0)
58998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return NULL;
59098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
59198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (plib == NULL)
59298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		plib = protolib_cache_default(cache, key, own_key);
59398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
59498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	return plib;
59598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata}
59698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
59798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machatastruct protolib *
59898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machataprotolib_cache_default(struct protolib_cache *cache,
59998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		       const char *key, int own_key)
60098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata{
60198a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	if (strdup_if(&key, key, !own_key) < 0) {
60298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		fprintf(stderr, "Couldn't cache default %s: %s\n",
60398a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			key, strerror(errno));
60498a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		return NULL;
60598a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	}
60698a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
60798a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	struct protolib *plib = build_default_config(cache, key);
60898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
60998a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	/* Whatever came out of this (even NULL), store it in
61098a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata	 * the cache.  */
61182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	attempt_to_cache(cache, key, plib);
61298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata
61382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return plib;
61482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
61582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
61682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machatastruct protolib *
617a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machataprotolib_cache_file(struct protolib_cache *cache,
618a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		    const char *filename, int own_filename)
61982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
62082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	{
62182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		struct protolib *plib;
62282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		if (DICT_FIND_VAL(&cache->protolibs, &filename, &plib) == 0)
62382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata			return plib;
62482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
62582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
62682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	FILE *stream = fopen(filename, "r");
62782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	if (stream == NULL)
62882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return NULL;
62982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
630b1ab2aefa199ea8e14e29bac78ae71030c2d4863Petr Machata	if (strdup_if(&filename, filename, !own_filename) < 0) {
631a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		fprintf(stderr, "Couldn't cache %s: %s\n",
632a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			filename, strerror(errno));
63382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		fclose(stream);
63482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return NULL;
63582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
63682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
637a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	struct protolib *new_plib = build_default_config(cache, filename);
638a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	if (new_plib == NULL
639a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	    || read_config_file(stream, filename, new_plib) < 0) {
64082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		fclose(stream);
641a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		if (own_filename)
64298a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata			free((char *) filename);
643a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		if (new_plib != NULL) {
644a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			protolib_destroy(new_plib);
645a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			free(new_plib);
646a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		}
64782ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata		return NULL;
64882ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	}
64982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
65082ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	attempt_to_cache(cache, filename, new_plib);
65182ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	fclose(stream);
65282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata	return new_plib;
65382ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
65482ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata
65582ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataint
65682ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machataprotolib_cache_protolib(struct protolib_cache *cache,
657a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			const char *filename, int own_filename,
658a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			struct protolib *plib)
65982ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata{
660b1ab2aefa199ea8e14e29bac78ae71030c2d4863Petr Machata	if (strdup_if(&filename, filename, !own_filename) < 0) {
661a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		fprintf(stderr, "Couldn't cache %s: %s\n",
662a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata			filename, strerror(errno));
663a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata		return -1;
664a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	}
665a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata
666a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	int rc = DICT_INSERT(&cache->protolibs, &filename, &plib);
667a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	if (rc < 0 && own_filename)
66898a7dce70986f2394d22ee5dd8ed355ceb2104b4Petr Machata		free((char *) filename);
669e56fe644f725f2c1c8308e7c2b5f9cd02e89eed0Petr Machata	if (rc == 0 && plib != NULL)
6707f1d856ea4882a23461886d0f589244cc11f0b2fPetr Machata		plib->refs++;
671a5e983bd5555c496a209f3e3a48e2826940b09f5Petr Machata	return rc;
67282ce0f8e3aefc3f833e7059f3cedeacedca0cad2Petr Machata}
67308cdf328add7b723b94b151866e5d0173662f6c6Petr Machata
674f70812ec281a829ca7a758337aacec58eca41550Petr Machatastatic void
675f70812ec281a829ca7a758337aacec58eca41550Petr Machatadestroy_global_config(void)
676f70812ec281a829ca7a758337aacec58eca41550Petr Machata{
677f70812ec281a829ca7a758337aacec58eca41550Petr Machata	protolib_cache_destroy(&g_protocache);
678f70812ec281a829ca7a758337aacec58eca41550Petr Machata	protolib_destroy(&legacy_typedefs);
679f70812ec281a829ca7a758337aacec58eca41550Petr Machata}
680f70812ec281a829ca7a758337aacec58eca41550Petr Machata
68108cdf328add7b723b94b151866e5d0173662f6c6Petr Machatavoid
68208cdf328add7b723b94b151866e5d0173662f6c6Petr Machatainit_global_config(void)
68308cdf328add7b723b94b151866e5d0173662f6c6Petr Machata{
68408cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	protolib_init(&legacy_typedefs);
68508cdf328add7b723b94b151866e5d0173662f6c6Petr Machata
686c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	struct arg_type_info *ptr_info = type_get_voidptr();
68708cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	static struct named_type voidptr_type;
688c65c24a7e4645559a0fb050ff5a96ec248827562Petr Machata	named_type_init(&voidptr_type, ptr_info, 0);
68908cdf328add7b723b94b151866e5d0173662f6c6Petr Machata
690f9f3df4c9e232dc06b769daa5edf489675c5cdfcPetr Machata	/* Build legacy typedefs first.  This is used by
691f9f3df4c9e232dc06b769daa5edf489675c5cdfcPetr Machata	 * protolib_cache_init call below.  */
69208cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	if (protolib_add_named_type(&legacy_typedefs, "addr", 0,
69308cdf328add7b723b94b151866e5d0173662f6c6Petr Machata				    &voidptr_type) < 0
69408cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	    || protolib_add_named_type(&legacy_typedefs, "file", 0,
69508cdf328add7b723b94b151866e5d0173662f6c6Petr Machata				       &voidptr_type) < 0) {
69608cdf328add7b723b94b151866e5d0173662f6c6Petr Machata		fprintf(stderr,
69708cdf328add7b723b94b151866e5d0173662f6c6Petr Machata			"Couldn't initialize aliases `addr' and `file'.\n");
698f9f3df4c9e232dc06b769daa5edf489675c5cdfcPetr Machata
699f70812ec281a829ca7a758337aacec58eca41550Petr Machata		exit(1);
70008cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	}
70108cdf328add7b723b94b151866e5d0173662f6c6Petr Machata
70208cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	if (protolib_cache_init(&g_protocache, NULL) < 0) {
70308cdf328add7b723b94b151866e5d0173662f6c6Petr Machata		fprintf(stderr, "Couldn't init prototype cache\n");
704f70812ec281a829ca7a758337aacec58eca41550Petr Machata		exit(1);
70508cdf328add7b723b94b151866e5d0173662f6c6Petr Machata	}
70608cdf328add7b723b94b151866e5d0173662f6c6Petr Machata
707f70812ec281a829ca7a758337aacec58eca41550Petr Machata	atexit(destroy_global_config);
70808cdf328add7b723b94b151866e5d0173662f6c6Petr Machata}
709