Remove MERGE_ALT_FORM merge mode
[platform/upstream/libxkbcommon.git] / src / context.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Author: Daniel Stone <daniel@fooishbar.org>
24  */
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <stdio.h>
29 #include <unistd.h>
30
31 #include "xkb-priv.h"
32 #include "atom.h"
33
34 struct xkb_context {
35     int refcnt;
36
37     darray(char *) includes;
38
39     /* xkbcomp needs to assign sequential IDs to XkbFile's it creates. */
40     int file_id;
41
42     struct atom_table *atom_table;
43 };
44
45 /**
46  * Append one directory to the context's include path.
47  */
48 _X_EXPORT int
49 xkb_context_include_path_append(struct xkb_context *ctx, const char *path)
50 {
51     struct stat stat_buf;
52     int err;
53     char *tmp;
54
55     err = stat(path, &stat_buf);
56     if (err != 0)
57         return 0;
58     if (!S_ISDIR(stat_buf.st_mode))
59         return 0;
60
61 #if defined(HAVE_EACCESS)
62     if (eaccess(path, R_OK | X_OK) != 0)
63         return 0;
64 #elif defined(HAVE_EUIDACCESS)
65     if (euidaccess(path, R_OK | X_OK) != 0)
66         return 0;
67 #endif
68
69     tmp = strdup(path);
70     if (!tmp)
71         return 0;
72
73     darray_append(ctx->includes, tmp);
74     return 1;
75 }
76
77 /**
78  * Append the default include directories to the context.
79  */
80 _X_EXPORT int
81 xkb_context_include_path_append_default(struct xkb_context *ctx)
82 {
83     const char *home;
84     char *user_path;
85     int err;
86
87     (void) xkb_context_include_path_append(ctx, DFLT_XKB_CONFIG_ROOT);
88
89     home = getenv("HOME");
90     if (!home)
91         return 1;
92     err = asprintf(&user_path, "%s/.xkb", home);
93     if (err <= 0)
94         return 1;
95     (void) xkb_context_include_path_append(ctx, user_path);
96     free(user_path);
97
98     return 1;
99 }
100
101 /**
102  * Remove all entries in the context's include path.
103  */
104 _X_EXPORT void
105 xkb_context_include_path_clear(struct xkb_context *ctx)
106 {
107     char **path;
108
109     darray_foreach(path, ctx->includes)
110         free(*path);
111
112     darray_free(ctx->includes);
113 }
114
115 /**
116  * xkb_context_include_path_clear() + xkb_context_include_path_append_default()
117  */
118 _X_EXPORT int
119 xkb_context_include_path_reset_defaults(struct xkb_context *ctx)
120 {
121     xkb_context_include_path_clear(ctx);
122     return xkb_context_include_path_append_default(ctx);
123 }
124
125 /**
126  * Returns the number of entries in the context's include path.
127  */
128 _X_EXPORT unsigned int
129 xkb_context_num_include_paths(struct xkb_context *ctx)
130 {
131     return darray_size(ctx->includes);
132 }
133
134 /**
135  * Returns the given entry in the context's include path, or NULL if an
136  * invalid index is passed.
137  */
138 _X_EXPORT const char *
139 xkb_context_include_path_get(struct xkb_context *ctx, unsigned int idx)
140 {
141     if (idx >= xkb_context_num_include_paths(ctx))
142         return NULL;
143
144     return darray_item(ctx->includes, idx);
145 }
146
147 int
148 xkb_context_take_file_id(struct xkb_context *ctx)
149 {
150     return ctx->file_id++;
151 }
152
153 /**
154  * Take a new reference on the context.
155  */
156 _X_EXPORT struct xkb_context *
157 xkb_context_ref(struct xkb_context *ctx)
158 {
159     ctx->refcnt++;
160     return ctx;
161 }
162
163 /**
164  * Drop an existing reference on the context, and free it if the refcnt is
165  * now 0.
166  */
167 _X_EXPORT void
168 xkb_context_unref(struct xkb_context *ctx)
169 {
170     if (--ctx->refcnt > 0)
171         return;
172
173     xkb_context_include_path_clear(ctx);
174     atom_table_free(ctx->atom_table);
175     free(ctx);
176 }
177
178 /**
179  * Create a new context.
180  */
181 _X_EXPORT struct xkb_context *
182 xkb_context_new(enum xkb_context_flags flags)
183 {
184     struct xkb_context *ctx = calloc(1, sizeof(*ctx));
185
186     if (!ctx)
187         return NULL;
188
189     ctx->refcnt = 1;
190
191     if (!(flags & XKB_CONTEXT_NO_DEFAULT_INCLUDES) &&
192         !xkb_context_include_path_append_default(ctx)) {
193         xkb_context_unref(ctx);
194         return NULL;
195     }
196
197     ctx->atom_table = atom_table_new();
198     if (!ctx->atom_table) {
199         xkb_context_unref(ctx);
200         return NULL;
201     }
202
203     return ctx;
204 }
205
206 xkb_atom_t
207 xkb_atom_intern(struct xkb_context *ctx, const char *string)
208 {
209     return atom_intern(ctx->atom_table, string);
210 }
211
212 char *
213 xkb_atom_strdup(struct xkb_context *ctx, xkb_atom_t atom)
214 {
215     return atom_strdup(ctx->atom_table, atom);
216 }
217
218 const char *
219 xkb_atom_text(struct xkb_context *ctx, xkb_atom_t atom)
220 {
221     return atom_text(ctx->atom_table, atom);
222 }