[1101] | 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 | //---------------------------------------------------------------------------
|
---|