00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066 #include "main.h"
00067
00068 extern struct dcc_t *dcc;
00069
00070
00071 typedef struct lang_st {
00072 struct lang_st *next;
00073 char *lang;
00074 char *section;
00075 } lang_sec;
00076
00077 typedef struct lang_pr {
00078 struct lang_pr *next;
00079 char *lang;
00080 } lang_pri;
00081
00082 typedef struct lang_t {
00083 int idx;
00084 char *text;
00085 struct lang_t *next;
00086 } lang_tab;
00087
00088 static lang_tab *langtab[64];
00089 static lang_sec *langsection = NULL;
00090 static lang_pri *langpriority = NULL;
00091
00092 static int del_lang(char *);
00093 static int add_message(int, char *);
00094 static void recheck_lang_sections(void);
00095 static void read_lang(char *);
00096 void add_lang_section(char *);
00097 int del_lang_section(char *);
00098 int exist_lang_section(char *);
00099 static char *get_specific_langfile(char *, lang_sec *);
00100 static char *get_langfile(lang_sec *);
00101 static int split_lang(char *, char **, char **);
00102 int cmd_loadlanguage(struct userrec *, int, char *);
00103
00104
00105
00106
00107
00108 void add_lang(char *lang)
00109 {
00110 lang_pri *lp = langpriority, *lpo = NULL;
00111
00112 while (lp) {
00113
00114 if (!strcmp(lang, lp->lang)) {
00115
00116 if (!lpo)
00117 return;
00118 lpo->next = lp->next;
00119 lp->next = lpo;
00120 langpriority = lp;
00121 return;
00122 }
00123 lpo = lp;
00124 lp = lp->next;
00125 }
00126
00127
00128 lp = nmalloc(sizeof(lang_pri));
00129 lp->lang = nmalloc(strlen(lang) + 1);
00130 strcpy(lp->lang, lang);
00131 lp->next = NULL;
00132
00133
00134 if (langpriority)
00135 lp->next = langpriority;
00136 langpriority = lp;
00137 debug1("LANG: Language loaded: %s", lang);
00138 }
00139
00140
00141
00142 static int del_lang(char *lang)
00143 {
00144 lang_pri *lp = langpriority, *lpo = NULL;
00145
00146 while (lp) {
00147
00148 if (!strcmp(lang, lp->lang)) {
00149 if (lpo)
00150 lpo->next = lp->next;
00151 else
00152 langpriority = lp->next;
00153 if (lp->lang)
00154 nfree(lp->lang);
00155 nfree(lp);
00156 debug1("LANG: Language unloaded: %s", lang);
00157 return 1;
00158 }
00159 lpo = lp;
00160 lp = lp->next;
00161 }
00162
00163 return 0;
00164 }
00165
00166 static int add_message(int lidx, char *ltext)
00167 {
00168 lang_tab *l = langtab[lidx & 63];
00169
00170 while (l) {
00171 if (l->idx && (l->idx == lidx)) {
00172 nfree(l->text);
00173 l->text = nmalloc(strlen(ltext) + 1);
00174 strcpy(l->text, ltext);
00175 return 1;
00176 }
00177 if (!l->next)
00178 break;
00179 l = l->next;
00180 }
00181 if (l) {
00182 l->next = nmalloc(sizeof(lang_tab));
00183 l = l->next;
00184 } else
00185 l = langtab[lidx & 63] = nmalloc(sizeof(lang_tab));
00186 l->idx = lidx;
00187 l->text = nmalloc(strlen(ltext) + 1);
00188 strcpy(l->text, ltext);
00189 l->next = 0;
00190 return 0;
00191 }
00192
00193
00194
00195
00196 static void recheck_lang_sections(void)
00197 {
00198 lang_sec *ls;
00199 char *langfile;
00200
00201 for (ls = langsection; ls && ls->section; ls = ls->next) {
00202 langfile = get_langfile(ls);
00203
00204 if (langfile) {
00205 read_lang(langfile);
00206 nfree(langfile);
00207 }
00208 }
00209 }
00210
00211
00212
00213 static void read_lang(char *langfile)
00214 {
00215 FILE *FLANG;
00216 char lbuf[512];
00217 char *ltext = NULL;
00218 char *ctmp, *ctmp1;
00219 int lidx;
00220 int lnew = 1;
00221 int lline = 1;
00222 int lskip = 0;
00223 int ltexts = 0;
00224 int ladd = 0, lupdate = 0;
00225
00226 FLANG = fopen(langfile, "r");
00227 if (FLANG == NULL) {
00228 putlog(LOG_MISC, "*", "LANG: unexpected: reading from file %s failed.",
00229 langfile);
00230 return;
00231 }
00232
00233 for (*(ltext = nmalloc(sizeof lbuf)) = 0; fgets(lbuf, sizeof lbuf, FLANG);
00234 ltext = nrealloc(ltext, strlen(ltext) + sizeof lbuf), lskip = 0) {
00235 if (lnew) {
00236 if ((lbuf[0] == '#') || (sscanf(lbuf, "%s", ltext) == EOF))
00237 lskip = 1;
00238 else if (sscanf(lbuf, "0x%x,", &lidx) != 1) {
00239 putlog(LOG_MISC, "*", "LANG: Malformed text line in %s at %d.",
00240 langfile, lline);
00241 lskip = 1;
00242 }
00243 if (lskip) {
00244 while (!strchr(lbuf, '\n')) {
00245 fgets(lbuf, 511, FLANG);
00246 lline++;
00247 }
00248 lline++;
00249 lnew = 1;
00250 continue;
00251 }
00252 strcpy(ltext, strchr(lbuf, ',') + 1);
00253 } else
00254 strcpy(strchr(ltext, 0), lbuf);
00255 if ((ctmp = strchr(ltext, '\n'))) {
00256 lline++;
00257 *ctmp = 0;
00258 if (ctmp[-1] == '\\') {
00259 lnew = 0;
00260 ctmp[-1] = 0;
00261 } else {
00262 ltexts++;
00263 lnew = 1;
00264
00265 for (ctmp1 = ctmp = ltext; *ctmp1; ctmp++, ctmp1++) {
00266 if ((*ctmp1 == '\\') && ctmp1[1] == 'n') {
00267 *ctmp = '\n';
00268 ctmp1++;
00269 } else if ((*ctmp1 == '\\') && ctmp1[1] == 't') {
00270 *ctmp = '\t';
00271 ctmp1++;
00272 } else
00273 *ctmp = *ctmp1;
00274 }
00275 *ctmp = 0;
00276 if (add_message(lidx, ltext)) {
00277 lupdate++;
00278 } else
00279 ladd++;
00280 }
00281 } else
00282 lnew = 0;
00283 }
00284 nfree(ltext);
00285 fclose(FLANG);
00286
00287 debug3("LANG: %d messages of %d lines loaded from %s", ltexts, lline,
00288 langfile);
00289 debug2("LANG: %d adds, %d updates to message table", ladd, lupdate);
00290 }
00291
00292
00293
00294 int exist_lang_section(char *section)
00295 {
00296 lang_sec *ls;
00297
00298 for (ls = langsection; ls; ls = ls->next)
00299 if (!strcmp(section, ls->section))
00300 return 1;
00301 return 0;
00302 }
00303
00304
00305
00306
00307 void add_lang_section(char *section)
00308 {
00309 char *langfile = NULL;
00310 lang_sec *ls, *ols = NULL;
00311 int ok = 0;
00312
00313 for (ls = langsection; ls; ols = ls, ls = ls->next)
00314
00315 if (!strcmp(section, ls->section))
00316 return;
00317
00318
00319 ls = nmalloc(sizeof(lang_sec));
00320 ls->section = nmalloc(strlen(section) + 1);
00321 strcpy(ls->section, section);
00322 ls->lang = NULL;
00323 ls->next = NULL;
00324
00325
00326 if (ols)
00327 ols->next = ls;
00328 else
00329 langsection = ls;
00330 debug1("LANG: Section loaded: %s", section);
00331
00332
00333 langfile = get_specific_langfile(BASELANG, ls);
00334 if (langfile) {
00335 read_lang(langfile);
00336 nfree(langfile);
00337 ok = 1;
00338 }
00339
00340 langfile = get_langfile(ls);
00341 if (!langfile) {
00342 if (!ok)
00343 putlog(LOG_MISC, "*", "LANG: No lang files found for section %s.",
00344 section);
00345 return;
00346 }
00347 read_lang(langfile);
00348 nfree(langfile);
00349 }
00350
00351 int del_lang_section(char *section)
00352 {
00353 lang_sec *ls, *ols;
00354
00355 for (ls = langsection, ols = NULL; ls; ols = ls, ls = ls->next)
00356 if (ls->section && !strcmp(ls->section, section)) {
00357 if (ols)
00358 ols->next = ls->next;
00359 else
00360 langsection = ls->next;
00361 nfree(ls->section);
00362 if (ls->lang)
00363 nfree(ls->lang);
00364 nfree(ls);
00365 debug1("LANG: Section unloaded: %s", section);
00366 return 1;
00367 }
00368 return 0;
00369 }
00370
00371 static char *get_specific_langfile(char *language, lang_sec *sec)
00372 {
00373 char *ldir = getenv("EGG_LANGDIR");
00374 char *langfile;
00375
00376 if (!ldir)
00377 ldir = LANGDIR;
00378 langfile = nmalloc(strlen(ldir) + strlen(sec->section) + strlen(language) +
00379 8);
00380 sprintf(langfile, "%s/%s.%s.lang", ldir, sec->section, language);
00381
00382 if (file_readable(langfile)) {
00383
00384 sec->lang = nrealloc(sec->lang, strlen(language) + 1);
00385 strcpy(sec->lang, language);
00386 return langfile;
00387 }
00388
00389 nfree(langfile);
00390 return NULL;
00391 }
00392
00393
00394
00395
00396 static char *get_langfile(lang_sec *sec)
00397 {
00398 char *langfile;
00399 lang_pri *lp;
00400
00401 for (lp = langpriority; lp; lp = lp->next) {
00402
00403 if (sec->lang && !strcmp(sec->lang, lp->lang))
00404 return NULL;
00405 langfile = get_specific_langfile(lp->lang, sec);
00406 if (langfile)
00407 return langfile;
00408 }
00409
00410 if (sec->lang)
00411 nfree(sec->lang);
00412 sec->lang = NULL;
00413 return NULL;
00414 }
00415
00416
00417
00418
00419
00420 static int split_lang(char *par, char **lang, char **section)
00421 {
00422 char *p;
00423
00424 p = strrchr(par, '/');
00425
00426 if (p)
00427 *section = p + 1;
00428 else
00429 *section = par;
00430 p = strchr(*section, '.');
00431 if (p)
00432 p[0] = 0;
00433 else
00434 return 0;
00435 *lang = p + 1;
00436 p = strstr(*lang, ".lang");
00437 if (p)
00438 p[0] = 0;
00439 return 1;
00440 }
00441
00442
00443
00444 int cmd_loadlanguage(struct userrec *u, int idx, char *par)
00445 {
00446 char *section, *lang, *buf;
00447
00448 dprintf(idx, "Note: This command is obsoleted by +lang.\n");
00449 if (!par || !par[0]) {
00450 dprintf(idx, "Usage: language <section>.<language>\n");
00451 return 0;
00452 }
00453 if (idx != DP_LOG)
00454 putlog(LOG_CMDS, "*", "#%s# language %s", dcc[idx].nick, par);
00455 buf = nmalloc(strlen(par) + 1);
00456 strcpy(buf, par);
00457 if (!split_lang(buf, &lang, §ion)) {
00458 nfree(buf);
00459 dprintf(idx, "Invalid parameter %s.\n", par);
00460 return 0;
00461 }
00462 add_lang(lang);
00463 add_lang_section(section);
00464 nfree(buf);
00465 recheck_lang_sections();
00466 return 0;
00467 }
00468
00469 static int cmd_plslang(struct userrec *u, int idx, char *par)
00470 {
00471 if (!par || !par[0]) {
00472 dprintf(idx, "Usage: +lang <language>\n");
00473 return 0;
00474 }
00475 putlog(LOG_CMDS, "*", "#%s# +lang %s", dcc[idx].nick, par);
00476 add_lang(par);
00477 recheck_lang_sections();
00478 return 0;
00479 }
00480
00481 static int cmd_mnslang(struct userrec *u, int idx, char *par)
00482 {
00483 if (!par || !par[0]) {
00484 dprintf(idx, "Usage: -lang <language>\n");
00485 return 0;
00486 }
00487 putlog(LOG_CMDS, "*", "#%s# -lang %s", dcc[idx].nick, par);
00488 if (!del_lang(par))
00489 dprintf(idx, "Language %s not found.\n", par);
00490 else
00491 recheck_lang_sections();
00492 return 0;
00493 }
00494
00495 static int cmd_plslsec(struct userrec *u, int idx, char *par)
00496 {
00497 if (!par || !par[0]) {
00498 dprintf(idx, "Usage: +lsec <section>\n");
00499 return 0;
00500 }
00501 putlog(LOG_CMDS, "*", "#%s# +lsec %s", dcc[idx].nick, par);
00502 add_lang_section(par);
00503 return 0;
00504 }
00505
00506 static int cmd_mnslsec(struct userrec *u, int idx, char *par)
00507 {
00508 if (!par || !par[0]) {
00509 dprintf(idx, "Usage: -lsec <section>\n");
00510 return 0;
00511 }
00512 putlog(LOG_CMDS, "*", "#%s# -lsec %s", dcc[idx].nick, par);
00513 if (!del_lang_section(par))
00514 dprintf(idx, "Section %s not found.\n", par);
00515 return 0;
00516 }
00517
00518 static int cmd_relang(struct userrec *u, int idx, char *par)
00519 {
00520 dprintf(idx, "Rechecking language sections...\n");
00521 recheck_lang_sections();
00522 return 0;
00523 }
00524
00525 static int cmd_languagedump(struct userrec *u, int idx, char *par)
00526 {
00527 lang_tab *l;
00528 char ltext2[512];
00529 int idx2, i;
00530
00531 putlog(LOG_CMDS, "*", "#%s# ldump %s", dcc[idx].nick, par);
00532 if (par[0]) {
00533
00534 if (strlen(par) > 2 && par[0] == '0' && par[1] == 'x')
00535 sscanf(par, "%x", &idx2);
00536 else
00537 idx2 = (int) strtol(par, (char **) NULL, 10);
00538 strcpy(ltext2, get_language(idx2));
00539 dprintf(idx, "0x%x: %s\n", idx2, ltext2);
00540 return 0;
00541 }
00542 dprintf(idx, " LANGIDX TEXT\n");
00543 for (i = 0; i < 64; i++)
00544 for (l = langtab[i]; l; l = l->next)
00545 dprintf(idx, "0x%x %s\n", l->idx, l->text);
00546 return 0;
00547 }
00548
00549 static char text[512];
00550 char *get_language(int idx)
00551 {
00552 lang_tab *l;
00553
00554 if (!idx)
00555 return "MSG-0-";
00556 for (l = langtab[idx & 63]; l; l = l->next)
00557 if (idx == l->idx)
00558 return l->text;
00559 egg_snprintf(text, sizeof text, "MSG%03X", idx);
00560 return text;
00561 }
00562
00563 int expmem_language()
00564 {
00565 lang_tab *l;
00566 lang_sec *ls;
00567 lang_pri *lp;
00568 int i, size = 0;
00569
00570 for (i = 0; i < 64; i++)
00571 for (l = langtab[i]; l; l = l->next) {
00572 size += sizeof(lang_tab);
00573 size += (strlen(l->text) + 1);
00574 }
00575 for (ls = langsection; ls; ls = ls->next) {
00576 size += sizeof(lang_sec);
00577 if (ls->section)
00578 size += strlen(ls->section) + 1;
00579 if (ls->lang)
00580 size += strlen(ls->lang) + 1;
00581 }
00582 for (lp = langpriority; lp; lp = lp->next) {
00583 size += sizeof(lang_pri);
00584 if (lp->lang)
00585 size += strlen(lp->lang) + 1;
00586 }
00587 return size;
00588 }
00589
00590
00591
00592 static int cmd_languagestatus(struct userrec *u, int idx, char *par)
00593 {
00594 int ltexts = 0;
00595 register int i, c, maxdepth = 0, used = 0, empty = 0;
00596 lang_tab *l;
00597 lang_sec *ls = langsection;
00598 lang_pri *lp = langpriority;
00599
00600 putlog(LOG_CMDS, "*", "#%s# lstat %s", dcc[idx].nick, par);
00601 for (i = 0; i < 64; i++) {
00602 c = 0;
00603 for (l = langtab[i]; l; l = l->next)
00604 c++;
00605 if (c > maxdepth)
00606 maxdepth = c;
00607 if (c)
00608 used++;
00609 else
00610 empty++;
00611 ltexts += c;
00612 }
00613 dprintf(idx, "Language code report:\n");
00614 dprintf(idx, " Table size : %d bytes\n", expmem_language());
00615 dprintf(idx, " Text messages: %d\n", ltexts);
00616 dprintf(idx, " %d used, %d unused, maxdepth %d, avg %f\n",
00617 used, empty, maxdepth, (float) ltexts / 64.0);
00618 if (lp) {
00619 int c = 0;
00620
00621 dprintf(idx, " Supported languages:");
00622 for (; lp; lp = lp->next) {
00623 dprintf(idx, "%s %s", c ? "," : "", lp->lang);
00624 c = 1;
00625 }
00626 dprintf(idx, "\n");
00627 }
00628 if (ls) {
00629 dprintf(idx, "\n SECTION LANG\n");
00630 dprintf(idx, " ==============================\n");
00631 for (; ls; ls = ls->next)
00632 dprintf(idx, " %-20s %s\n", ls->section,
00633 ls->lang ? ls->lang : "<none>");
00634 }
00635 return 0;
00636 }
00637
00638
00639
00640 static int tcl_language STDVAR
00641 {
00642 char *lang, *section, *buf;
00643
00644 putlog(LOG_MISC, "*", "The Tcl command 'language' is obsolete. Use "
00645 "'addlang' instead.");
00646 BADARGS(2, 2, " language");
00647
00648 buf = nmalloc(strlen(argv[1]) + 1);
00649 strcpy(buf, argv[1]);
00650
00651 if (!split_lang(buf, &lang, §ion)) {
00652 Tcl_AppendResult(irp, "Invalid parameter", NULL);
00653 nfree(buf);
00654 return TCL_ERROR;
00655 }
00656 add_lang(lang);
00657
00658 add_lang_section(section);
00659 nfree(buf);
00660 recheck_lang_sections();
00661 return TCL_OK;
00662 }
00663
00664 static int tcl_plslang STDVAR
00665 {
00666 BADARGS(2, 2, " language");
00667
00668 add_lang(argv[1]);
00669 recheck_lang_sections();
00670
00671 return TCL_OK;
00672 }
00673
00674 static int tcl_mnslang STDVAR
00675 {
00676 BADARGS(2, 2, " language");
00677
00678 if (!del_lang(argv[1])) {
00679 Tcl_AppendResult(irp, "Language not found.", NULL);
00680 return TCL_ERROR;
00681 }
00682 recheck_lang_sections();
00683
00684 return TCL_OK;
00685 }
00686
00687 static int tcl_addlangsection STDVAR
00688 {
00689 BADARGS(2, 2, " section");
00690
00691 add_lang_section(argv[1]);
00692 return TCL_OK;
00693 }
00694
00695 static int tcl_dellangsection STDVAR
00696 {
00697 BADARGS(2, 2, " section");
00698
00699 if (!del_lang_section(argv[1])) {
00700 Tcl_AppendResult(irp, "Section not found", NULL);
00701 return TCL_ERROR;
00702 }
00703 return TCL_OK;
00704 }
00705
00706 static int tcl_relang STDVAR
00707 {
00708 recheck_lang_sections();
00709 return TCL_OK;
00710 }
00711
00712 static cmd_t langdcc[] = {
00713 {"language", "n", cmd_loadlanguage, NULL},
00714 {"+lang", "n", cmd_plslang, NULL},
00715 {"-lang", "n", cmd_mnslang, NULL},
00716 {"+lsec", "n", cmd_plslsec, NULL},
00717 {"-lsec", "n", cmd_mnslsec, NULL},
00718 {"ldump", "n", cmd_languagedump, NULL},
00719 {"lstat", "n", cmd_languagestatus, NULL},
00720 {"relang", "n", cmd_relang, NULL},
00721 {NULL, NULL, NULL, NULL}
00722 };
00723
00724 static tcl_cmds langtcls[] = {
00725 {"language", tcl_language},
00726 {"addlang", tcl_plslang},
00727 {"dellang", tcl_mnslang},
00728 {"addlangsection", tcl_addlangsection},
00729 {"dellangsection", tcl_dellangsection},
00730 {"relang", tcl_relang},
00731 {NULL, NULL}
00732 };
00733
00734 void init_language(int flag)
00735 {
00736 int i;
00737 char *deflang;
00738
00739 if (flag) {
00740 for (i = 0; i < 32; i++)
00741 langtab[i] = 0;
00742
00743
00744
00745 add_lang(BASELANG);
00746
00747 deflang = getenv("EGG_LANG");
00748 if (deflang)
00749 add_lang(deflang);
00750 add_lang_section("core");
00751 } else {
00752 add_tcl_commands(langtcls);
00753 add_builtins(H_dcc, langdcc);
00754 }
00755 }