#pragma implementation #include #include #include #include #include #include #include #include #include #include #include "internal.h" #include #include #include using namespace std; #if defined (unix) #include #define O_BINARY 0 static const char *translat_readall(int fd, int size) { return (const char*)mmap(0,size,PROT_READ,MAP_SHARED,fd,0); } #else #if defined (UNIX) // Just to test the DOS/Windows mode in Unix. #include #define O_BINARY 0 #else #include #endif static const char *translat_readall(int fd, int size) { char *ptm = (char*)malloc(size); if (ptm != NULL){ if (read(fd,ptm,size)!=size){ fprintf (stderr,"Can't read messages database\n"); } }else{ fprintf (stderr,"Can't allocate memory for messages\n"); } close (fd); return ptm; } #endif #include "translat.h" static TRANSLATE_SYSTEM_REQ *first = NULL; PUBLIC TRANSLATE_SYSTEM_REQ::TRANSLATE_SYSTEM_REQ( const char *_sysname, const char **&_global_var, // Will point to an array // of message (char*) int _nb_expected, int _version) : global_var (_global_var) { nb_expected = _nb_expected; version = _version; /* #Specification: translate / dictionnary request A dictionnary request is done simply by declaring a static variable of type TRANSLATE_SYSTEM_REQ. We generally defined this variable in the source module which is always used within a system. Sometime, there is no such a module but indeed a few module (A library) which are candidate to be included in every program which use the librairy. It is possible to declare several static TRANSLATE_SYSTEM_REQ, one in every module we need. These request should use obviously the same name and the same global variable. Special macros are automagically defined by msgscan to insure consistency. */ TRANSLATE_SYSTEM_REQ *pt = first; while (pt != NULL){ if (strcmp(pt->sysname,_sysname)==0)break; pt = pt->next; } if (pt == NULL){ next = first; first = this; sysname = _sysname; } } static char *pterr = NULL; #define MAXERR_SIZE 2000 /* Print an error message and increment the err counter */ static void translat_err (const char *msg, ...) { va_list list; va_start (list,msg); pterr += vsnprintf (pterr,MAXERR_SIZE,msg,list); va_end (list); } struct LANGS{ vector langs; LANGS(){ langs.push_back(NULL); langs.push_back(NULL); } }; static map lang_switch; static void translat_alloc ( BDICT_SYSTEM *tbsys, int nbsys, const char *base_file, // Start of mmap file const char *ptm, // start of indexes unsigned langnum) // Lang number for multiple language support (web apps) { /* The static variable "first" points to a linked list of TRANSLATE_SYSTEM_REQ. Each member corresponds to a dictionary to load. OLD If we find a given dictionary in tbsys, then we remove the TRANSLATE_SYSTEM_REQ object from the linked list. Ultimatly, first wiil point to NULL. /OLD This strategy allows various things -One program may be composed of several dictionaries (one per directory generally) -One program may spread its dictionaries in several message files. This is especially useful when you are using various libraries where each one supplies its own message file. translat_alloc will be called several times. -One program (linuxconf for one) may have its own message file and each module provides also its message file. */ TRANSLATE_SYSTEM_REQ *req = first; while (req != NULL){ unsigned offset = 0; BDICT_SYSTEM *ptsys = tbsys; int i; for (i=0; inbmsg; if (strcmp(req->sysname,ptsys->name)==0){ if (req->version > ptsys->version){ translat_err ("sub-dictionnary %s: Invalid version %d < %d\n" ,req->sysname,ptsys->version,req->version); }else if (req->nb_expected > ptsys->nbmsg){ translat_err ("sub-dictionnary %s: Not enough messages %d < %d\n" ,req->sysname,ptsys->nbmsg,req->nb_expected); }else{ req->global_var = (const char**)malloc(nbmsg*sizeof(char*)); lang_switch[&req->global_var].langs[langnum] = req->global_var; const char **ptvar = req->global_var; unsigned *ptoff = (unsigned*)(ptm + offset); for (int m=0; mname,m,base_file,*ptvar); } } break; }else{ offset += nbmsg * sizeof(unsigned); } } req = req->next; } } /* Read a BDICT_HEADER in a binary compatible way on all architecture Return the pointer at the end of BDICT_HEADER in the buffer */ static const char *translat_readheader ( const char *ptm, BDICT_HEADER &hd) { unsigned short *val = (unsigned short*)ptm; hd.magic = ntohs (val[0]); hd.version = ntohs (val[1]); hd.nbsys = ntohs (val[2]); // printf ("magic = %x version = %x nbsys = %x\n",hd.magic,hd.version,hd.nbsys); return ptm+6; } /* Read a BDICT_SYSTEM in a binary compatible way on all architecture Return the pointer at the end of BDICT_SYSTEM in the buffer */ static const char *translat_readsys ( const char *ptm, BDICT_SYSTEM &sys) { strcpy (sys.name,ptm); ptm += sizeof(sys.name); unsigned short *val = (unsigned short*)ptm; sys.version = ntohs (val[0]); sys.nbmsg = ntohs (val[1]); return ptm+4; } static string default_lang = "eng"; static vector search_path; /* Load the message dictionnary. Terminate the application if any error. */ static int translat_loaderr ( const char *basename, // base name of the dictionnary // the language selection will supply // the extension. const char *lang, unsigned langnum, char errmsg[MAXERR_SIZE]) // Will contain the error message { int ret = -1; errmsg[0] = '\0'; pterr = errmsg; bool showerr = getenv ("SHOWDICERR")!=NULL; for (unsigned i=0; i errmsg ? -1 : 0; break; } } return ret; } static vector tblang; unsigned nblang = 0; void translat_setlang (const char *lang) { static bool done_once = false; if (!done_once){ done_once = true; default_lang = lang; nblang = str_splitline(lang,',',tblang); } } void translat_setdictdir (const char *path) { bool found = false; for (unsigned i=0; i 1){ // Load several langs at once (used for web application) for (unsigned i=0; iglobal_var) == lang_switch.end()){ some_missing = true; fprintf (stderr,"Unknown dictionnary %s\n",req->sysname); } req = req->next; } if (some_missing) exit(-1); for (map::iterator it=lang_switch.begin(); it != lang_switch.end(); it++){ for (unsigned i=1; isecond.langs.size(); i++){ if (it->second.langs[i] == NULL) it->second.langs[i] = it->second.langs[0]; } } } void translat_selectlang(const char *lang) { unsigned nolang = 0; for (unsigned i=0; i::iterator it=lang_switch.begin(); it != lang_switch.end(); it++){ (*it->first) = it->second.langs[nolang]; } }