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