1a8fdb4bcSmrg/*
2a8fdb4bcSmrgCopyright (c) 2001 by Juliusz Chroboczek
3a8fdb4bcSmrg
4a8fdb4bcSmrgPermission is hereby granted, free of charge, to any person obtaining a copy
5a8fdb4bcSmrgof this software and associated documentation files (the "Software"), to deal
6a8fdb4bcSmrgin the Software without restriction, including without limitation the rights
7a8fdb4bcSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8a8fdb4bcSmrgcopies of the Software, and to permit persons to whom the Software is
9a8fdb4bcSmrgfurnished to do so, subject to the following conditions:
10a8fdb4bcSmrg
11a8fdb4bcSmrgThe above copyright notice and this permission notice shall be included in
12a8fdb4bcSmrgall copies or substantial portions of the Software.
13a8fdb4bcSmrg
14a8fdb4bcSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15a8fdb4bcSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16a8fdb4bcSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17a8fdb4bcSmrgAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18a8fdb4bcSmrgLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19a8fdb4bcSmrgOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20a8fdb4bcSmrgTHE SOFTWARE.
21a8fdb4bcSmrg*/
2277683534Smrg
2377683534Smrg#ifdef HAVE_CONFIG_H
2477683534Smrg# include "config.h"
2577683534Smrg#endif
26a8fdb4bcSmrg
27a8fdb4bcSmrg#include <stdlib.h>
28a8fdb4bcSmrg#include <stdio.h>
29a8fdb4bcSmrg#include <string.h>
30a8fdb4bcSmrg
3177683534Smrg#include "luit.h"
32a8fdb4bcSmrg#include "parser.h"
3377683534Smrg#include "sys.h"
34a8fdb4bcSmrg
35a8fdb4bcSmrgstatic char keyword[MAX_KEYWORD_LENGTH];
36a8fdb4bcSmrg
37a8fdb4bcSmrgstatic void
38a8fdb4bcSmrgskipEndOfLine(FILE *f, int c)
39a8fdb4bcSmrg{
4077683534Smrg    if (c == 0)
4177683534Smrg	c = getc(f);
4277683534Smrg
4377683534Smrg    for (;;)
4477683534Smrg	if (c <= 0 || c == '\n')
4577683534Smrg	    return;
4677683534Smrg	else
4777683534Smrg	    c = getc(f);
48a8fdb4bcSmrg}
49a8fdb4bcSmrg
50a8fdb4bcSmrgstatic int
51a8fdb4bcSmrgdrainWhitespace(FILE *f, int c)
52a8fdb4bcSmrg{
5377683534Smrg    if (c == 0)
5477683534Smrg	c = getc(f);
55a8fdb4bcSmrg
56a8fdb4bcSmrg    while (c == '#' || c == ' ' || c == '\t') {
5777683534Smrg	if (c <= 0)
5877683534Smrg	    return 0;
5977683534Smrg	if (c == '#') {
6077683534Smrg	    skipEndOfLine(f, c);
6177683534Smrg	    return '\n';
6277683534Smrg	}
6377683534Smrg	c = getc(f);
64a8fdb4bcSmrg    }
65a8fdb4bcSmrg
66a8fdb4bcSmrg    return c;
67a8fdb4bcSmrg}
68a8fdb4bcSmrg
69a8fdb4bcSmrgstatic int
70a8fdb4bcSmrggetString(FILE *f, int string_end, int *c_return)
71a8fdb4bcSmrg{
72a8fdb4bcSmrg    int i = 0;
73a8fdb4bcSmrg    int c;
74a8fdb4bcSmrg
75a8fdb4bcSmrg    c = getc(f);
7677683534Smrg    while (c > 0) {
7777683534Smrg	if (c == string_end)
7877683534Smrg	    break;
7977683534Smrg	if (c == '\\') {
8077683534Smrg	    c = getc(f);
8177683534Smrg	    if (c == '\n')
8277683534Smrg		continue;
8377683534Smrg	}
8477683534Smrg	keyword[i++] = (char) c;
8577683534Smrg	if (i >= MAX_KEYWORD_LENGTH)
8677683534Smrg	    return TOK_ERROR;
8777683534Smrg	c = getc(f);
88a8fdb4bcSmrg    }
89a8fdb4bcSmrg
9077683534Smrg    if (c <= 0)
9177683534Smrg	return TOK_ERROR;
92a8fdb4bcSmrg    keyword[i] = '\0';
93a8fdb4bcSmrg    *c_return = c;
94a8fdb4bcSmrg    return TOK_KEYWORD;
95a8fdb4bcSmrg}
96a8fdb4bcSmrg
97a8fdb4bcSmrgstatic int
98a8fdb4bcSmrggetToken(FILE *f, int c, int parse_assignments, int *c_return)
99a8fdb4bcSmrg{
100a8fdb4bcSmrg    int i;
101a8fdb4bcSmrg    c = drainWhitespace(f, c);
102a8fdb4bcSmrg
10377683534Smrg    if (c < 0)
10477683534Smrg	return TOK_EOF;
10577683534Smrg    if (c == '\n') {
10677683534Smrg	*c_return = 0;
10777683534Smrg	return TOK_EOL;
108a8fdb4bcSmrg    }
109a8fdb4bcSmrg
11077683534Smrg    if (parse_assignments && c == '=') {
11177683534Smrg	*c_return = 0;
11277683534Smrg	return TOK_EQUALS;
113a8fdb4bcSmrg    }
114a8fdb4bcSmrg
11577683534Smrg    if (c == '\'' || c == '"')
11677683534Smrg	return getString(f, c, c_return);
117a8fdb4bcSmrg
118a8fdb4bcSmrg    i = 0;
11977683534Smrg    while (c > 0 && c != ' ' && c != '\t' && c != '\n') {
12077683534Smrg	if (c == '\\') {
12177683534Smrg	    c = getc(f);
12277683534Smrg	    if (c == '\n')
12377683534Smrg		continue;
12477683534Smrg	}
12577683534Smrg	keyword[i++] = (char) c;
12677683534Smrg	if (i >= MAX_KEYWORD_LENGTH)
12777683534Smrg	    return TOK_ERROR;
12877683534Smrg	c = getc(f);
12977683534Smrg	if (parse_assignments && c == '=')
13077683534Smrg	    break;
131a8fdb4bcSmrg    }
132a8fdb4bcSmrg
13377683534Smrg    *c_return = c < 0 ? 0 : c;
134a8fdb4bcSmrg    keyword[i] = '\0';
135a8fdb4bcSmrg    return TOK_KEYWORD;
136a8fdb4bcSmrg}
137a8fdb4bcSmrg
138a8fdb4bcSmrg/* Can parse both the old and new formats for locale.alias */
139a8fdb4bcSmrgstatic int
140a8fdb4bcSmrgparseTwoTokenLine(FILE *f, char *first, char *second)
141a8fdb4bcSmrg{
142a8fdb4bcSmrg    int c = 0;
143a8fdb4bcSmrg    int tok;
144a8fdb4bcSmrg
145a8fdb4bcSmrg  again:
14677683534Smrg
147a8fdb4bcSmrg    tok = getToken(f, c, 0, &c);
14877683534Smrg    if (tok == TOK_EOF)
14977683534Smrg	return -1;
15077683534Smrg    else if (tok == TOK_EOL)
15177683534Smrg	goto again;
15277683534Smrg    else if (tok == TOK_KEYWORD) {
15377683534Smrg	size_t len = strlen(keyword);
15477683534Smrg	if (keyword[len - 1] == ':')
15577683534Smrg	    keyword[len - 1] = '\0';
15677683534Smrg	strcpy(first, keyword);
157a8fdb4bcSmrg    } else
15877683534Smrg	return -2;
159a8fdb4bcSmrg
160a8fdb4bcSmrg    tok = getToken(f, c, 0, &c);
16177683534Smrg    if (tok == TOK_KEYWORD) {
16277683534Smrg	strcpy(second, keyword);
163a8fdb4bcSmrg    } else
16477683534Smrg	return -2;
165a8fdb4bcSmrg
166a8fdb4bcSmrg    tok = getToken(f, c, 0, &c);
16777683534Smrg    if (tok != TOK_EOL)
16877683534Smrg	return -2;
169a8fdb4bcSmrg
170a8fdb4bcSmrg    return 0;
171a8fdb4bcSmrg}
172a8fdb4bcSmrg
173a8fdb4bcSmrgchar *
174a8fdb4bcSmrgresolveLocale(const char *locale)
175a8fdb4bcSmrg{
176a8fdb4bcSmrg    FILE *f;
177a8fdb4bcSmrg    char first[MAX_KEYWORD_LENGTH], second[MAX_KEYWORD_LENGTH];
178a8fdb4bcSmrg    char *resolved = NULL;
179a8fdb4bcSmrg    int rc;
18077683534Smrg    int found = 0;
18177683534Smrg
18277683534Smrg    f = fopen(locale_alias, "r");
18377683534Smrg
18477683534Smrg    if (f != NULL) {
18577683534Smrg	do {
18677683534Smrg	    rc = parseTwoTokenLine(f, first, second);
18777683534Smrg	    if (rc < -1)
18877683534Smrg		break;
18977683534Smrg	    if (!strcmp(first, locale)) {
19077683534Smrg		resolved = strmalloc(second);
19177683534Smrg		found = 1;
19277683534Smrg		break;
19377683534Smrg	    }
19477683534Smrg	} while (rc >= 0);
19577683534Smrg
19677683534Smrg	if (!found) {
19777683534Smrg	    if (resolved == NULL) {
19877683534Smrg		resolved = strmalloc(locale);
19977683534Smrg	    }
20077683534Smrg	}
20177683534Smrg
20277683534Smrg	fclose(f);
20377683534Smrg    } else {
20477683534Smrg	perror(locale_alias);
205a8fdb4bcSmrg    }
206a8fdb4bcSmrg
207a8fdb4bcSmrg    return resolved;
208a8fdb4bcSmrg}
209