-
Notifications
You must be signed in to change notification settings - Fork 52
/
lang.c
367 lines (342 loc) · 17.1 KB
/
lang.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
//---------------------------------------------------------------------------
// File name: lang.c
//---------------------------------------------------------------------------
#include "launchelf.h"
#define lang(id, name, value) char Str_##name[] = value;
#include "lang.h"
#undef lang
Language Lang_Default[] = {
#define lang(id, name, value) {Str_##name},
#include "lang.h"
#undef lang
{NULL}};
Language Lang_String[sizeof(Lang_Default) / sizeof(Lang_Default[0])];
Language Lang_Extern[sizeof(Lang_Default) / sizeof(Lang_Default[0])];
Language *External_Lang_Buffer = NULL;
//---------------------------------------------------------------------------
// get_LANG_string is the main parser called for each language dependent
// string in a language header file. (eg: "Francais.h" or "Francais.lng")
// Call values for all input arguments should be addresses of string pointers
// LANG_p_p is for file to be scanned, moved to point beyond scanned data.
// id_p_p is for a string defining the index value (suitable for 'atoi')
// value_p_p is for the string value itself (not NUL-terminated)
// The function returns the length of each string found, but -1 at EOF,
// and various error codes less than -1 (-2 etc) for various syntax errors,
// which also applies to EOF occurring where valid macro parts are expected.
//---------------------------------------------------------------------------
int get_LANG_string(char **LANG_p_p, char **id_p_p, char **value_p_p)
{
const char *cp;
char *ip;
char *vp;
char *tp = *LANG_p_p;
int ret, length;
ip = NULL;
vp = NULL;
ret = -1;
start_line:
while (*tp <= ' ' && *tp > '\0')
tp += 1; // Skip leading whitespace, if any
if (*tp == '\0')
goto exit; // but exit at EOF
// Current pos is potential "lang(" entry, but we must verify this
if (tp[0] == '/' && tp[1] == '/') // It may be a comment line
{ // We must skip a comment line
while (*tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // Seek line end
goto start_line; // Go back to try next line
}
ret = -2;
// Here tp points to a non-zero string that is not a comment
if (strncmp(tp, "lang", 4))
goto exit; // Return error if not 'lang' macro
tp += 4; // but if it is, step past that name
ret = -3;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
ret = -4;
// Here tp points to a non-zero string that should be an opening parenthesis
if (*tp != '(')
goto exit; // Return error if no opening parenthesis
tp += 1; // but if it is, step past this character
ret = -5;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
ret = -6;
// Here tp points to a non-zero string that should be an index number
if (*tp < '0' || *tp > '9')
goto exit; // Return error if it's not a number
ip = tp; // but if it is, save this pos as id start
while (*tp >= '0' && *tp <= '9')
tp += 1; // skip past the index number
ret = -7;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
ret = -8;
// Here tp points to a non-zero string that should be a comma
if (*tp != ',')
goto exit; // Return error if no comma after index
tp += 1; // but if present, step past that comma
ret = -9;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
ret = -10;
// Here tp points to a non-zero string that should be a symbolic string name
// But we don't need to process this for language switch purposes, so we ignore it
// This may be changed later, to use the name for generating error messages
while (*tp != ',' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // seek inline comma
if (*tp != ',')
goto exit; // Return error if no comma after string name
tp += 1; // but if present, step past that comma
ret = -11;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
ret = -12;
// Here tp points to a non-zero string that should be the opening quote character
if (*tp != '\"')
goto exit; // Return error if no opening quote
tp += 1; // but if present, step past that quote
ret = -13;
vp = tp; // save this pos as value start
close_quote:
while (*tp != '\"' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // seek inline quote
if (*tp != '\"')
return -13; // Return error if no closing quote
cp = tp - 1; // save previous pos as check pointer
tp += 1; // step past the quote character
if (*cp == '\\')
goto close_quote; // if this was an 'escaped' quote, try again
// Here tp points to the character after the closing quote.
length = (tp - 1) - vp; // prepare string length for return value
ret = -14;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
ret = -15;
// Here tp points to a non-zero string that should be closing parenthesis
if (*tp != ')')
goto exit; // Return error if no closing parenthesis
tp += 1; // but if present, step past the parenthesis
ret = -16;
while (*tp <= ' ' && *tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // skip inline whitespace
if (*tp == '\0')
goto exit; // but exit at EOF
// Here tp points to a non-zero string that should be line end or a comment
if (tp[0] != '/' || tp[1] != '/')
goto finish_line; // if no comment, go handle line end
ret = -17;
while (*tp != '\r' && *tp != '\n' && *tp > '\0')
tp += 1; // Seek line end
if (*tp == '\0')
goto exit; // but exit at EOF
finish_line:
ret = -18;
if (*tp != '\r' && *tp != '\n')
goto exit; // Return error if not valid line end
if (tp[0] == '\r' && tp[1] == '\n')
tp += 1; // Step an extra pos for CR+LF
tp += 1; // Step past valid line end
// Here tp points beyond the line of the processed string, so we're done
ret = length;
exit:
*LANG_p_p = tp; // return new LANG file position
*id_p_p = ip; // return found index
*value_p_p = vp; // return found string value
return ret; // return control to caller
}
// Ends get_LANG_string
//---------------------------------------------------------------------------
void Init_Default_Language(void)
{
memcpy(Lang_String, Lang_Default, sizeof(Lang_String));
}
// Ends Init_Default_Language
//---------------------------------------------------------------------------
void Load_External_Language(void)
{
int error_id = -1;
int test = 0;
u32 index = 0;
char filePath[MAX_PATH];
char *file_bp, *file_tp, *lang_bp, *lang_tp, *oldf_tp = NULL;
char *id_p, *value_p;
int lang_size = 0;
int fd;
if (External_Lang_Buffer != NULL) { // if an external buffer was allocated before
free(External_Lang_Buffer); // release that buffer before the new attempt
External_Lang_Buffer = NULL;
}
const Language *Lang = Lang_Default;
memcpy(Lang_String, Lang, sizeof(Lang_String));
if (strlen(setting->lang_file) != 0) { // if language file string set
error_id = -2;
genFixPath(setting->lang_file, filePath);
fd = genOpen(filePath, O_RDONLY);
if (fd >= 0) { // if file opened OK
int file_size = (int)genLseek(fd, 0, SEEK_END);
error_id = -3;
if (file_size > 0) { // if file size OK
error_id = -4;
file_bp = (char *)malloc(file_size + 1);
if (file_bp == NULL)
goto aborted_1;
error_id = -5;
genLseek(fd, 0, SEEK_SET);
if (genRead(fd, file_bp, file_size) != file_size)
goto release_1;
file_bp[file_size] = '\0'; // enforce termination at buffer end
error_id = -6;
file_tp = file_bp;
while (1) {
oldf_tp = file_tp;
test = get_LANG_string(&file_tp, &id_p, &value_p);
if (test == -1) // if EOF reached without other error
break; // break from the loop normally
if (test < 0) // At any fatal error result
goto release_1; // go release file buffer
index = atoi(id_p); // get the string index
if (index >= LANG_COUNT) // At any fatal error result
goto release_1; // go release file buffer
lang_size += test + 1; // Include terminator space for total size
}
// Here lang_size is the space needed for real language buffer,
error_id = -7;
lang_bp = (char *)malloc(lang_size + 1); // allocate real language buffer
if (lang_bp == NULL)
goto release_1;
// We're ready to read language strings, but must first init all pointers
// to use default strings, for any indexes left undefined by the file
memcpy(Lang_Extern, Lang, sizeof(Lang_Extern));
file_tp = file_bp;
lang_tp = lang_bp;
while ((test = get_LANG_string(&file_tp, &id_p, &value_p)) >= 0) {
index = atoi(id_p); // get the string index
Lang_Extern[index].String = lang_tp; // save pointer to this string base
strncpy(lang_tp, value_p, test); // transfer the string
lang_tp[test] = '\0'; // transfer a terminator
lang_tp += test + 1; // move dest pointer past this string
}
External_Lang_Buffer = (Language *)lang_bp; // Save base pointer for releases
Lang = Lang_Extern;
error_id = 0;
release_1:
free(file_bp);
} // end if clause for file size OK
aborted_1:
genClose(fd);
} // end if clause for file opened OK
} // end if language file string set
if (error_id < -1) {
char tmp_s[80 * 16];
int pos = 0, stp = 0;
sprintf(tmp_s,
"LNG loading failed with error_id==%d and test==%d\n"
"The latest string index (possibly invalid) was %d\n"
"%n",
error_id, test, index, &stp);
pos += stp;
if (error_id == -2) { // if file open failure
sprintf(tmp_s + pos,
"This was a failure to open the file:\n"
"\"%s\"\n",
filePath);
}
if (error_id == -6) { // if parsing error
char t1_s[102], t2_s[102];
strncpy(t1_s, oldf_tp, 100);
t1_s[100] = '\0';
strncpy(t2_s, file_tp, 100);
t2_s[100] = '\0';
sprintf(tmp_s + pos,
"This was a parsing error when trying to parse the text:\n"
"\"%s\"\n"
"That attempt failed somehow, after reaching this point:\n"
"\"%s\"\n",
t1_s, t2_s);
}
strcat(tmp_s, "Use either OK or CANCEL to continue (no diff)");
ynDialog(tmp_s);
}
memcpy(Lang_String, Lang, sizeof(Lang_String));
if (strlen(setting->Misc) > 0) {
int i;
for (i = 0; i < 16; i++) { // Loop to rename the ELF paths with new language for launch keys
if ((i < 12) || (setting->LK_Flag[i] != 0)) {
if (!strncmp(setting->LK_Path[i], setting->Misc, strlen(setting->Misc))) {
const char *tmp;
tmp = strrchr(setting->LK_Path[i], '/');
if (!strcmp(tmp + 1, setting->Misc_PS2Disc + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(PS2Disc));
else if (!strcmp(tmp + 1, setting->Misc_FileBrowser + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(FileBrowser));
else if (!strcmp(tmp + 1, setting->Misc_PS2Browser + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(PS2Browser));
else if (!strcmp(tmp + 1, setting->Misc_PS2Net + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(PS2Net));
else if (!strcmp(tmp + 1, setting->Misc_PS2PowerOff + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(PS2PowerOff));
else if (!strcmp(tmp + 1, setting->Misc_HddManager + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(HddManager));
else if (!strcmp(tmp + 1, setting->Misc_TextEditor + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(TextEditor));
else if (!strcmp(tmp + 1, setting->Misc_JpgViewer + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(JpgViewer));
else if (!strcmp(tmp + 1, setting->Misc_Configure + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(Configure));
else if (!strcmp(tmp + 1, setting->Misc_Load_CNFprev + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(Load_CNFprev));
else if (!strcmp(tmp + 1, setting->Misc_Load_CNFnext + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(Load_CNFnext));
else if (!strcmp(tmp + 1, setting->Misc_Set_CNF_Path + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(Set_CNF_Path));
else if (!strcmp(tmp + 1, setting->Misc_Load_CNF + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(Load_CNF));
else if (!strcmp(tmp + 1, setting->Misc_ShowFont + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(ShowFont));
else if (!strcmp(tmp + 1, setting->Misc_Debug_Info + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(Debug_Info));
else if (!strcmp(tmp + 1, setting->Misc_About_uLE + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(About_uLE));
else if (!strcmp(tmp + 1, setting->Misc_OSDSYS + strlen(setting->Misc)))
sprintf(setting->LK_Path[i], "%s/%s", LNG(MISC), LNG(OSDSYS));
} // end if Misc
} // end if LK assigned
} // end for
} // end if Misc Initialized
sprintf(setting->Misc, "%s/", LNG(MISC));
sprintf(setting->Misc_PS2Disc, "%s/%s", LNG(MISC), LNG(PS2Disc));
sprintf(setting->Misc_FileBrowser, "%s/%s", LNG(MISC), LNG(FileBrowser));
sprintf(setting->Misc_PS2Browser, "%s/%s", LNG(MISC), LNG(PS2Browser));
sprintf(setting->Misc_PS2Net, "%s/%s", LNG(MISC), LNG(PS2Net));
sprintf(setting->Misc_PS2PowerOff, "%s/%s", LNG(MISC), LNG(PS2PowerOff));
sprintf(setting->Misc_HddManager, "%s/%s", LNG(MISC), LNG(HddManager));
sprintf(setting->Misc_TextEditor, "%s/%s", LNG(MISC), LNG(TextEditor));
sprintf(setting->Misc_JpgViewer, "%s/%s", LNG(MISC), LNG(JpgViewer));
sprintf(setting->Misc_Configure, "%s/%s", LNG(MISC), LNG(Configure));
sprintf(setting->Misc_Load_CNFprev, "%s/%s", LNG(MISC), LNG(Load_CNFprev));
sprintf(setting->Misc_Load_CNFnext, "%s/%s", LNG(MISC), LNG(Load_CNFnext));
sprintf(setting->Misc_Set_CNF_Path, "%s/%s", LNG(MISC), LNG(Set_CNF_Path));
sprintf(setting->Misc_Load_CNF, "%s/%s", LNG(MISC), LNG(Load_CNF));
sprintf(setting->Misc_ShowFont, "%s/%s", LNG(MISC), LNG(ShowFont));
sprintf(setting->Misc_Debug_Info, "%s/%s", LNG(MISC), LNG(Debug_Info));
sprintf(setting->Misc_About_uLE, "%s/%s", LNG(MISC), LNG(About_uLE));
sprintf(setting->Misc_OSDSYS, "%s/%s", LNG(MISC), LNG(OSDSYS));
}
// Ends Load_External_Language
//---------------------------------------------------------------------------
// End of file: lang.c
//---------------------------------------------------------------------------