parser.c revision 77683534
1/*
2Copyright (c) 2001 by Juliusz Chroboczek
3
4Permission is hereby granted, free of charge, to any person obtaining a copy
5of this software and associated documentation files (the "Software"), to deal
6in the Software without restriction, including without limitation the rights
7to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8copies of the Software, and to permit persons to whom the Software is
9furnished to do so, subject to the following conditions:
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20THE SOFTWARE.
21*/
22
23#ifdef HAVE_CONFIG_H
24# include "config.h"
25#endif
26
27#include <stdlib.h>
28#include <stdio.h>
29#include <string.h>
30
31#include "luit.h"
32#include "parser.h"
33#include "sys.h"
34
35static char keyword[MAX_KEYWORD_LENGTH];
36
37static void
38skipEndOfLine(FILE *f, int c)
39{
40    if (c == 0)
41	c = getc(f);
42
43    for (;;)
44	if (c <= 0 || c == '\n')
45	    return;
46	else
47	    c = getc(f);
48}
49
50static int
51drainWhitespace(FILE *f, int c)
52{
53    if (c == 0)
54	c = getc(f);
55
56    while (c == '#' || c == ' ' || c == '\t') {
57	if (c <= 0)
58	    return 0;
59	if (c == '#') {
60	    skipEndOfLine(f, c);
61	    return '\n';
62	}
63	c = getc(f);
64    }
65
66    return c;
67}
68
69static int
70getString(FILE *f, int string_end, int *c_return)
71{
72    int i = 0;
73    int c;
74
75    c = getc(f);
76    while (c > 0) {
77	if (c == string_end)
78	    break;
79	if (c == '\\') {
80	    c = getc(f);
81	    if (c == '\n')
82		continue;
83	}
84	keyword[i++] = (char) c;
85	if (i >= MAX_KEYWORD_LENGTH)
86	    return TOK_ERROR;
87	c = getc(f);
88    }
89
90    if (c <= 0)
91	return TOK_ERROR;
92    keyword[i] = '\0';
93    *c_return = c;
94    return TOK_KEYWORD;
95}
96
97static int
98getToken(FILE *f, int c, int parse_assignments, int *c_return)
99{
100    int i;
101    c = drainWhitespace(f, c);
102
103    if (c < 0)
104	return TOK_EOF;
105    if (c == '\n') {
106	*c_return = 0;
107	return TOK_EOL;
108    }
109
110    if (parse_assignments && c == '=') {
111	*c_return = 0;
112	return TOK_EQUALS;
113    }
114
115    if (c == '\'' || c == '"')
116	return getString(f, c, c_return);
117
118    i = 0;
119    while (c > 0 && c != ' ' && c != '\t' && c != '\n') {
120	if (c == '\\') {
121	    c = getc(f);
122	    if (c == '\n')
123		continue;
124	}
125	keyword[i++] = (char) c;
126	if (i >= MAX_KEYWORD_LENGTH)
127	    return TOK_ERROR;
128	c = getc(f);
129	if (parse_assignments && c == '=')
130	    break;
131    }
132
133    *c_return = c < 0 ? 0 : c;
134    keyword[i] = '\0';
135    return TOK_KEYWORD;
136}
137
138/* Can parse both the old and new formats for locale.alias */
139static int
140parseTwoTokenLine(FILE *f, char *first, char *second)
141{
142    int c = 0;
143    int tok;
144
145  again:
146
147    tok = getToken(f, c, 0, &c);
148    if (tok == TOK_EOF)
149	return -1;
150    else if (tok == TOK_EOL)
151	goto again;
152    else if (tok == TOK_KEYWORD) {
153	size_t len = strlen(keyword);
154	if (keyword[len - 1] == ':')
155	    keyword[len - 1] = '\0';
156	strcpy(first, keyword);
157    } else
158	return -2;
159
160    tok = getToken(f, c, 0, &c);
161    if (tok == TOK_KEYWORD) {
162	strcpy(second, keyword);
163    } else
164	return -2;
165
166    tok = getToken(f, c, 0, &c);
167    if (tok != TOK_EOL)
168	return -2;
169
170    return 0;
171}
172
173char *
174resolveLocale(const char *locale)
175{
176    FILE *f;
177    char first[MAX_KEYWORD_LENGTH], second[MAX_KEYWORD_LENGTH];
178    char *resolved = NULL;
179    int rc;
180    int found = 0;
181
182    f = fopen(locale_alias, "r");
183
184    if (f != NULL) {
185	do {
186	    rc = parseTwoTokenLine(f, first, second);
187	    if (rc < -1)
188		break;
189	    if (!strcmp(first, locale)) {
190		resolved = strmalloc(second);
191		found = 1;
192		break;
193	    }
194	} while (rc >= 0);
195
196	if (!found) {
197	    if (resolved == NULL) {
198		resolved = strmalloc(locale);
199	    }
200	}
201
202	fclose(f);
203    } else {
204	perror(locale_alias);
205    }
206
207    return resolved;
208}
209