Rename xkbcomp/misc.h to xkbcomp-priv.h and use it
[platform/upstream/libxkbcommon.git] / src / xkbcomp / path.c
1 /************************************************************
2  Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc.
3
4  Permission to use, copy, modify, and distribute this
5  software and its documentation for any purpose and without
6  fee is hereby granted, provided that the above copyright
7  notice appear in all copies and that both that copyright
8  notice and this permission notice appear in supporting
9  documentation, and that the name of Silicon Graphics not be
10  used in advertising or publicity pertaining to distribution
11  of the software without specific prior written permission.
12  Silicon Graphics makes no representation about the suitability
13  of this software for any purpose. It is provided "as is"
14  without any express or implied warranty.
15
16  SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
17  SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
18  AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
19  GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
20  DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21  DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
22  OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION  WITH
23  THE USE OR PERFORMANCE OF THIS SOFTWARE.
24
25  ********************************************************/
26
27 #include <errno.h>
28 #include <limits.h>
29
30 #include "xkbcomp-priv.h"
31
32 /**
33  * Extract the first token from an include statement.
34  * @param str_inout Input statement, modified in-place. Can be passed in
35  * repeatedly. If str_inout is NULL, the parsing has completed.
36  * @param file_rtrn Set to the include file to be used.
37  * @param map_rtrn Set to whatever comes after ), if any.
38  * @param nextop_rtrn Set to the next operation in the complete statement.
39  * @param extra_data Set to the string between ( and ), if any.
40  *
41  * @return true if parsing was succcessful, false for an illegal string.
42  *
43  * Example: "evdev+aliases(qwerty)"
44  *      str_inout = aliases(qwerty)
45  *      nextop_retrn = +
46  *      extra_data = NULL
47  *      file_rtrn = evdev
48  *      map_rtrn = NULL
49  *
50  * 2nd run with "aliases(qwerty)"
51  *      str_inout = NULL
52  *      file_rtrn = aliases
53  *      map_rtrn = qwerty
54  *      extra_data = NULL
55  *      nextop_retrn = ""
56  *
57  */
58 bool
59 XkbParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn,
60                    char *nextop_rtrn, char **extra_data)
61 {
62     char *tmp, *str, *next;
63
64     str = *str_inout;
65     if ((*str == '+') || (*str == '|'))
66     {
67         *file_rtrn = *map_rtrn = NULL;
68         *nextop_rtrn = *str;
69         next = str + 1;
70     }
71     else if (*str == '%')
72     {
73         *file_rtrn = *map_rtrn = NULL;
74         *nextop_rtrn = str[1];
75         next = str + 2;
76     }
77     else
78     {
79         /* search for tokens inside the string */
80         next = strpbrk(str, "|+");
81         if (next)
82         {
83             /* set nextop_rtrn to \0, next to next character */
84             *nextop_rtrn = *next;
85             *next++ = '\0';
86         }
87         else
88         {
89             *nextop_rtrn = '\0';
90             next = NULL;
91         }
92         /* search for :, store result in extra_data */
93         tmp = strchr(str, ':');
94         if (tmp != NULL)
95         {
96             *tmp++ = '\0';
97             *extra_data = uDupString(tmp);
98         }
99         else
100         {
101             *extra_data = NULL;
102         }
103         tmp = strchr(str, '(');
104         if (tmp == NULL)
105         {
106             *file_rtrn = uDupString(str);
107             *map_rtrn = NULL;
108         }
109         else if (str[0] == '(')
110         {
111             free(*extra_data);
112             return false;
113         }
114         else
115         {
116             *tmp++ = '\0';
117             *file_rtrn = uDupString(str);
118             str = tmp;
119             tmp = strchr(str, ')');
120             if ((tmp == NULL) || (tmp[1] != '\0'))
121             {
122                 free(*file_rtrn);
123                 free(*extra_data);
124                 return false;
125             }
126             *tmp++ = '\0';
127             *map_rtrn = uDupString(str);
128         }
129     }
130     if (*nextop_rtrn == '\0')
131         *str_inout = NULL;
132     else if ((*nextop_rtrn == '|') || (*nextop_rtrn == '+'))
133         *str_inout = next;
134     else
135         return false;
136     return true;
137 }
138
139 /***====================================================================***/
140
141 /**
142  * Return the xkb directory based on the type.
143  */
144 const char *
145 XkbDirectoryForInclude(unsigned type)
146 {
147     switch (type)
148     {
149     case XkmSemanticsFile:
150         return "semantics";
151     case XkmLayoutFile:
152         return "layout";
153     case XkmKeymapFile:
154         return "keymap";
155     case XkmKeyNamesIndex:
156         return "keycodes";
157     case XkmTypesIndex:
158         return "types";
159     case XkmSymbolsIndex:
160         return "symbols";
161     case XkmCompatMapIndex:
162         return "compat";
163     case XkmGeometryIndex:
164         return "geometry";
165     case XkmRulesFile:
166         return "rules";
167     default:
168         return "";
169     }
170 }
171
172 /***====================================================================***/
173
174 /**
175  * Search for the given file name in the include directories.
176  *
177  * @param context the XKB context containing the include paths
178  * @param type one of XkbTypesIndex, XkbCompatMapIndex, ..., or
179  *             XkbSemanticsFile, XkmKeymapFile, ...
180  * @param pathReturn is set to the full path of the file if found.
181  *
182  * @return an FD to the file or NULL. If NULL is returned, the value of
183  * pathRtrn is undefined.
184  */
185 FILE *
186 XkbFindFileInPath(struct xkb_context *context,
187                   const char *name, unsigned type, char **pathRtrn)
188 {
189     size_t i;
190     int ret;
191     FILE *file = NULL;
192     char buf[PATH_MAX];
193     const char *typeDir;
194
195     typeDir = XkbDirectoryForInclude(type);
196     for (i = 0; i < xkb_context_num_include_paths(context); i++)
197     {
198         ret = snprintf(buf, sizeof(buf), "%s/%s/%s",
199                        xkb_context_include_path_get(context, i), typeDir, name);
200         if (ret >= (ssize_t)sizeof(buf))
201         {
202             ERROR("File name (%s/%s/%s) too long\n",
203                   xkb_context_include_path_get(context, i), typeDir, name);
204             ACTION("Ignored\n");
205             continue;
206         }
207         file = fopen(buf, "r");
208         if (file == NULL) {
209             ERROR("Couldn't open file (%s/%s/%s): %s\n",
210                   xkb_context_include_path_get(context, i), typeDir, name,
211                   strerror(-errno));
212             ACTION("Ignored\n");
213             continue;
214         }
215         break;
216     }
217
218     if ((file != NULL) && (pathRtrn != NULL))
219         *pathRtrn = strdup(buf);
220     return file;
221 }