#include #include #include #include #include #include #include #include #include #include #include "internal.h" #ifdef UNIX #define MAXIMUM_PATH PATH_MAX #else #define MAXIMUM_PATH 128 #endif #define MISSING_MESSAGE "#???#" /* Print an error message in a popup Stubs to avoid linking the world */ void xconf_error (const char *msg, ...) { va_list list; va_start (list,msg); vfprintf (stderr,msg,list); va_end (list); } /* #Specification: translation / principle The translation mecanism used by linuxconf is fairly different from other system in use. Most system use an external dictionary which can be translated without recompiling the source. Linuxconf use a similar setup except the dictionary is updated from the source. First msgscan is used to produce/update dictionnaries by scanning all source file. It looks for macros like # MSG_U(ID,"english message") # or already translated ones # MSG_B(ID,"english message","french message") # From that, it produce a dictionary. This disctionary is then compiled and produce one include file per dictionary and a resource message file which contain several dictionary. One program may very well used several dictionary and a dictionary may be compiled in many message resource file. */ static const char *msgcomp_getmsg ( TR_STRING *t, const char *lang) { const char *ret = NULL; while (*lang != '\0'){ ret = t->getmsg(lang[0]); if (ret != NULL) break; lang++; } return ret; } static const char *msgcomp_getmsg ( TR_STRING *t, TR_STRINGS *trans, // Alternative dictionary to use const char *lang, const char *sysname) // Use to print error message // If NULL, no error needed { const char *ret = NULL; TR_STRING *tt = trans->getitem(t->getid()); if (tt != NULL) ret = msgcomp_getmsg (tt,lang); if (ret == NULL) ret = msgcomp_getmsg(t,lang); if (ret == NULL && sysname != NULL){ fprintf (stderr,"Missing message %s, system %s\n" ,t->getid(),sysname); } return ret; } static int write_header (const BDICT_HEADER &head, FILE *fout) { unsigned short val = htons (head.magic); int len = fwrite (&val,1,sizeof(val),fout); val = htons (head.version); len += fwrite (&val,1,sizeof(val),fout); val = htons (head.nbsys); len += fwrite (&val,1,sizeof(val),fout); // printf ("len header %d\n",len); return len; } static int write_sys (const BDICT_SYSTEM &sys, FILE *fout) { int len = fwrite (sys.name,1,sizeof(sys.name),fout); unsigned short val = htons (sys.version); len += fwrite (&val,1,sizeof(val),fout); val = htons (sys.nbmsg); len += fwrite (&val,1,sizeof(val),fout); // printf ("len system %d\n",len); return len; } static int write_offset (int &offset, FILE *fout) { int32_t val = htonl (offset); return fwrite (&val,sizeof(val),1,fout); } class TR_STRINGS_COMP{ public: TR_STRINGS ref; // Reference dictionary TR_STRINGS trans; // Translation /*~PROTOBEG~ TR_STRING_COMP */ /*~PROTOEND~ TR_STRING_COMP */ }; static int msgcomp_write ( const char *outfile, TR_STRINGS_COMP trs[], char *sysnames[], int nbsys, char *lang) // Language to generate // Instead of being a letter, it is a string of // letter. The first one is the prefered one // the other are fallback if the first is missing { int ret = -1; FILE *fout = fopen (outfile,"wb"); if (fout == NULL){ fprintf (stderr,"Can't open file %s (%s)\n" ,outfile,strerror(errno)); }else{ // We write the header ret = 0; BDICT_HEADER hd; hd.magic = BDICT_MAGIC; hd.version = BDICT_VERSION; hd.nbsys = nbsys; int offset_msg = write_header (hd,fout); // Then the header of each system int i; for (i=0; iref.getversion(); sys.nbmsg = tr->ref.getnb(); int size_sys = write_sys (sys,fout); offset_msg += size_sys + sys.nbmsg*sizeof(int32_t); } // Make sure the offsets are properly alligned in the file while ((offset_msg % sizeof(offset_msg)) != 0){ static char pad = 0; fwrite (&pad,1,1,fout); offset_msg++; } // Then the lookup table for each system // offset_msg now point to the beginning of the raw messages // area for (i=0; iref.getnb(); TR_STRINGS *trans = &tr->trans; for (int m=0; mref.getitem(m); write_offset (offset_msg,fout); const char *msg = msgcomp_getmsg (t,trans,lang ,sysnames[i]); if (msg == NULL) msg = MISSING_MESSAGE; char buf[10000]; str_compile (msg,buf); offset_msg += strlen (buf)+1; } } for (i=0; iref.getnb(); TR_STRINGS *trans = &tr->trans; for (int m=0; mref.getitem(m); const char *msg = msgcomp_getmsg (t,trans,lang,NULL); if (msg == NULL) msg = MISSING_MESSAGE; char buf[10000]; str_compile (msg,buf); int len = strlen (buf)+1; fwrite (buf,len,1,fout); } } fclose (fout); } return ret; } static bool msgcomp_exist (const char *path) { struct stat st; return stat(path,&st)!=-1; } int main (int _argc, char *_argv[]) { char *argv[200]; int argc = anlparm (_argc,_argv,argv); int ret = -1; if (argc < 4){ fprintf (stderr,"msgcomp -ppath [-ppath ...] resfile lang_select dictionary ...\n"); }else{ char **tbsys = (char**)malloc(argc*sizeof(char*)); ret = 0; int a; const char *paths[100]; paths[0] = paths[1] = ""; int nbpath = 0; for (a=1; aref.read (path); char *pt = strrchr (syspath,'/'); if (pt != NULL) syspath = pt+1; tbsys[i-a] = strdup(syspath); if (tr->ref.getnb()==0){ fprintf (stderr,"Empty dictionary %s\n" ,argv[i]); ret = -1; } readone = true; }else{ printf (" %s\n",path); tr->trans.read (path); } } } if (!readone){ printf ("Missing dictionnary : %s\n",syspath); ret = -1; } } if (ret != -1){ ret = msgcomp_write (res,trs,tbsys,argc-a,lang); }else{ fprintf (stderr ,"**** There were some error(s)\n" "**** No message produced\n"); } } return ret; }