| 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 |
//--------------------------------------------------------------------------- |