Subversion Repositories wimsdev

Rev

Rev 15442 | Rev 15482 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18. /*  This is an internal program,
  19.  * used to index modules for search engine.
  20.  */
  21.  
  22. #include "../Lib/libwims.h"
  23. #include "translator_.h"
  24. #include "suffix.h"
  25.  
  26. #define MAX_LANGS    MAX_LANGUAGES
  27. #define MAX_MODULES    65536
  28. char *moduledir=    "public_html/modules";
  29. char *sheetdir=     "public_html/bases/sheet";
  30. char *glossarydir=  "public_html/scripts/data/glossary";
  31. char *dicdir=       "public_html/bases";
  32. char *outdir=       "public_html/bases/site2";
  33. char *sheetoutdir=  "public_html/bases/sheet/index";
  34. char *glossaryoutdir=  "public_html/scripts/data/glossary/index";
  35. char *maindic=      "sys/words";
  36. char *groupdic=     "sys/wgrp/wgrp";
  37. char *suffixdic=    "sys/suffix";
  38. char *domaindic=    "sys/domaindic";
  39. char *ignoredic=    "sys/indignore";
  40. char *conffile=     "log/wims.conf";
  41. char *mlistbase=    "lists";
  42.  
  43. char lang[MAX_LANGS][4]={
  44.     "en","fr","cn","es","it","nl","si","ca","pt"
  45. };
  46. #define DEFAULT_LANGCNT    6
  47. char allang[MAX_LANGS][4]={
  48.     "en","fr","cn","es","it","nl","de","si","ca","pt"
  49. };
  50. #define allangcnt 8
  51. char ignore[MAX_LANGS][MAX_LINELEN+1];
  52. char mlistfile[MAX_LANGS][256];
  53. int langcnt;
  54. FILE *langf, *titf, *descf, *weightf, *robotf, *indf, *listf, *addrf, *serialf, *authorf, *versionf, *remf;
  55.  
  56. struct cat {
  57.     char *name;
  58.     char typ;
  59. } cat[]={
  60.     {"all_types", 'A'},
  61.     {"exercise",  'X'},
  62.     {"oef",       'O'},
  63.     {"tool",      'T'},
  64.     {"recreation",'R'},
  65.     {"reference", 'Y'},
  66.     {"document",  'D'},
  67.     {"popup",     'P'},
  68.     {"datamodule",'M'}
  69. };
  70. #define catno (sizeof(cat)/sizeof(cat[0]))
  71.  
  72. struct mod {
  73.     char *name;
  74.     unsigned char langs[MAX_LANGS];
  75.     int counts[MAX_LANGS];
  76.     int langcnt;
  77. } mod[MAX_MODULES];
  78.  
  79. // serial-> the name of the module indexed by serial, lang and its classe
  80. struct revmod {
  81.     char name[MAX_MODULELEN+1];
  82.     int lang;
  83.     int imod;
  84. } revmod[MAX_MODULES];
  85. int modcnt;
  86.  
  87. char *mlist;
  88. char *sheetindex[]={
  89.   "title", "description",
  90.   "duration", "severity",
  91.   "level", "domain",
  92.   "keywords", "reserved1", "reserved2", "information"
  93. };
  94. /* correspond to the order of sheetindex */
  95. char *glindex[]={
  96.   "gl_title", "gl_description",
  97.   "", "",
  98.   "gl_level", "gl_domain",
  99.   "gl_keywords","","",""};
  100.  
  101. #define SHEETINDEX_NO (sizeof(sheetindex)/sizeof(sheetindex[0]))
  102. char gsindbuf[SHEETINDEX_NO+1][MAX_LINELEN+1];
  103.  
  104. /* do not modify the order, correspond to the order in the sheet file */
  105. enum{s_title, s_description,
  106.       s_duration, s_severity,
  107.       s_level, s_domain,
  108.       s_keywords, s_reserved1, s_reserved2,
  109.       s_information
  110. };
  111.  
  112. char *modindex[]={
  113.   "title", "description",
  114.   "author", "address", "copyright",
  115.   "version", "wims_version", "language",
  116.   "category", "level", "domain", "keywords",
  117.   "keywords_ca", "keywords_en", "keywords_fr", "keywords_it", "keywords_nl",
  118.   "title_ca", "title_en", "title_fr", "title_it", "title_nl",
  119.   "require"
  120. };
  121. #define MODINDEX_NO (sizeof(modindex)/sizeof(modindex[0]))
  122. char indbuf[MODINDEX_NO][MAX_LINELEN+1];
  123. enum{i_title, i_description,
  124.   i_author,i_address,i_copyright,
  125.   i_version,i_wims_version,i_language,
  126.   i_category,i_level,i_domain,i_keywords,
  127.   i_keywords_ca,i_keywords_en,i_keywords_fr,i_keywords_it,i_keywords_nl,
  128.   i_title_ca,i_title_en,i_title_fr,i_title_it,i_title_nl,
  129.   i_require
  130. };
  131.  
  132. char *module_special_file[]={
  133.   "intro","help","about"
  134. };
  135. #define MODSPEC_NO (sizeof(module_special_file)/sizeof(module_special_file[0]))
  136. char module_language[4];
  137.  
  138. char *mdicbuf, *gdicbuf, *ddicbuf, *gentry, *mentry, *dentry;
  139.  
  140. int gentrycount, mentrycount, dentrycount;
  141.  
  142.  
  143. /*  fold known accented letters to unaccented, other strange characters to space
  144.  *  apostrophe is among the exceptions to be kept (important for multi-word expressions)
  145.  */
  146. void deaccent2(char *p)
  147. {
  148.   char *sp;
  149.   char *v;
  150.   for(sp=p;*sp;sp++) {
  151.   if(*sp<0 && (v=strchr(acctab,*sp))!=NULL)
  152.     *sp=*(deatab+(v-acctab));
  153.   if(!isalnum(*sp) && strchr(",.&$+*",*sp)==0) *sp=' ';
  154.   else *sp=tolower(*sp);
  155.   }
  156. }
  157.  
  158. /*  translate everything non-alphanumeric into space */
  159. void towords(char *p)
  160. {
  161.   char *pp;
  162.   for(pp=p;*pp;pp++) if(!isalnum(*pp) && strchr("&$+*",*pp)==0) *pp=' ';
  163. }
  164.  
  165. /*  Find first occurrence of word */
  166. char *wordchr2(char *p, char *w)
  167. {
  168.   char *r;
  169.  
  170.   for(r=strstr(p,w);r!=NULL &&
  171.     ( (r>p && !isspace(*(r-1))) || (!isspace(*(r+strlen(w))) && *(r+strlen(w))!=0) );
  172.   r=strstr(r+1,w));
  173.   return r;
  174. }
  175.  
  176. char *find_tag_end(char *p)
  177. {
  178.   char *pp;
  179.   pp=p; if(*pp=='<') pp++;
  180.   for(; *pp && *pp!='>'; pp++) {
  181.     if(*pp=='<') {
  182.       pp=find_tag_end(pp)-1; continue;
  183.     }
  184.     if(*pp=='"') {
  185.       pp=strchr(pp+1,'"');
  186.       if(pp==NULL) return p+strlen(p); else continue;
  187.     }
  188.     if(*pp=='\'') {
  189.       pp=strchr(pp+1,'\'');
  190.       if(pp==NULL) return p+strlen(p); else continue;
  191.     }
  192.   }
  193.   if(*pp=='>') pp++;
  194.   return pp;
  195. }
  196.  
  197. char *find_tag(char *p, char *tag)
  198. {
  199.   char *pp;
  200.   int len;
  201.   len=strlen(tag);
  202.   for(pp=strchr(p,'<'); pp!=NULL && *pp; pp=strchr(pp+1,'<')) {
  203.     if(strncasecmp(pp+1,tag,len)==0 && !isalnum(*(pp+1+len))) return pp;
  204.   }
  205.   return p+strlen(p);
  206. }
  207.  
  208. /*  remove all html tags */
  209. void detag(char *p)
  210. {
  211.   char *pp, *p2;
  212.   for(pp=strchr(p,'<'); pp!=NULL; pp=strchr(pp,'<')) {
  213.     p2=find_tag_end(pp);
  214.     if(*p2==0) {*pp=0; return; }
  215.     ovlstrcpy(pp,p2);
  216.   }
  217. }
  218.  
  219. /* add a space after comma to see end of words */
  220.  
  221. void comma(char *p)
  222. {
  223.   char *pp;
  224.   for(pp=strchr(p,','); pp; pp=strchr(pp+1,','))
  225.     string_modify3(p,pp,pp+1,", ");
  226. }
  227.  
  228. /* _getdef from lines.c except the error msg*/
  229. void _getdef(char buf[], char *name, char value[])
  230. {
  231.   char *p1, *p2, *p3, *p4;
  232.  
  233.   if(*name==0) goto nothing;      /* this would create segfault. */
  234.   for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) {
  235.     p2=find_word_start(p1+strlen(name));
  236.     if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue;
  237.     p3=p1; while(p3>buf && *(p3-1)!='\n') p3--;
  238.     p3=find_word_start(p3);
  239.     if(p3<p1 && *p3!='!') continue;
  240.     if(p3<p1) {
  241.       p3++; p4=find_word_end(p3);
  242.       if(find_word_start(p4)!=p1) continue;
  243.       if(p4-p3!=3 || (strncmp(p3,"set",3)!=0 &&
  244.            strncmp(p3,"let",3)!=0 &&
  245.            strncmp(p3,"def",3)!=0)) {
  246.         if(p4-p3!=6 || strncmp(p3,"define",6)!=0) continue;
  247.       }
  248.     }
  249.     p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2);
  250.     p2=find_word_start(p2);
  251.     if(p2>p3) goto nothing;
  252.     /*if(p3-p2>=MAX_LINELEN) user_error("cmd_output_too_long");*/
  253.     memmove(value,p2,p3-p2); value[p3-p2]=0;
  254.     strip_trailing_spaces(value); return;
  255.   }
  256. nothing:
  257.   value[0]=0;
  258. }
  259.  
  260. /*  Get variable definition from a file.
  261.  * Result stored in buffer value of length MAX_LINELEN.
  262.  */
  263. void getdef(char *fname, char *name, char value[])
  264. {
  265.   FILE *f;
  266.   char *buf;
  267.   int l;
  268.  
  269.   value[0]=0;
  270.   f=fopen(fname,"r"); if(f==NULL) return;
  271.   fseek(f,0,SEEK_END); l=ftell(f); fseek(f,0,SEEK_SET);
  272.   buf=xmalloc(l+256); l=fread(buf,1,l,f);
  273.   fclose(f);
  274.   if(l<=0) return; else buf[l]=0;
  275.   _getdef(buf,name,value);
  276.   free(buf);
  277. }
  278.  
  279. void init(void)
  280. {
  281.   char buf[MAX_LINELEN+1];
  282.   char *p1,*p2,*s;
  283.   int i,l;
  284.   FILE *f;
  285.  
  286.   s=getenv("modind_outdir"); if(s!=NULL && *s!=0) outdir=s;
  287.   s=getenv("modind_sheetdir"); if(s!=NULL && *s!=0) sheetdir=s;
  288.   s=getenv("modind_sheetoutdir"); if(s!=NULL && *s!=0) sheetoutdir=s;
  289.   s=getenv("modind_glossaryoutdir"); if(s!=NULL && *s!=0) glossaryoutdir=s;
  290. /* take the langs declared in conffile */
  291.   getdef(conffile,"site_languages",buf);
  292.   langcnt=0;
  293.   for(p1=buf;*p1;p1++) if(!isalnum(*p1)) *p1=' ';
  294.   for(p1=find_word_start(buf); *p1 && langcnt<MAX_LANGS; p1=find_word_start(p2)) {
  295.     p2=find_word_end(p1);
  296.     if(p2!=p1+2 || !isalpha(*p1) || !isalpha(*(p1+1))) continue;
  297.     memmove(lang[langcnt],p1,2); lang[langcnt++][2]=0;
  298.   }
  299.   if(langcnt==0) {/*  default languages */
  300.     langcnt=DEFAULT_LANGCNT;
  301.   }
  302.   for(i=0;i<langcnt;i++) {
  303.     snprintf(buf,sizeof(buf),"%s/%s.%s",dicdir,ignoredic,lang[i]);
  304.     f=fopen(buf,"r"); if(f==NULL) continue;
  305.     l=fread(ignore[i],1,MAX_LINELEN,f);fclose(f);
  306.     if(l<0 || l>=MAX_LINELEN) l=0;
  307.     ignore[i][l]=0;
  308.   }
  309. }
  310. /*  Preparation of data */
  311. void prep(void)
  312. {
  313.   char buf[MAX_LINELEN+1];
  314.   char *p1,*p2,*s,*old;
  315.   int i,l,thislang,t;
  316.   modcnt=0; old="";
  317.   snprintf(buf,sizeof(buf),"%s/addr",outdir);
  318.   addrf=fopen(buf,"w");
  319.   if(!addrf) { fprintf(stderr,"modind: error creating output files addr.\n"); exit(1);}
  320.   snprintf(buf,sizeof(buf),"%s/serial",outdir);
  321.   serialf=fopen(buf,"w");
  322.   if(!serialf) { fprintf(stderr,"modind: error creating output files serial.\n"); exit(1);}
  323.  
  324.   s=getenv("mlist"); if(s==NULL) exit(1);
  325.   l=strlen(s); if(l<0 || l>100*MAX_LINELEN) exit(1);
  326.   mlist=xmalloc(l+16); ovlstrcpy(mlist,s);
  327.  
  328.   for(t=0, p1=find_word_start(mlist); *p1 && modcnt<MAX_MODULES;
  329.         p1=find_word_start(p2), t++) {
  330.     p2=find_word_end(p1);
  331.     l=p2-p1; if(*p2) *p2++=0;
  332.     fprintf(addrf,"%d:%s\n",t,p1);
  333.     fprintf(serialf,"%s:%d\n",p1,t);
  334.     thislang=-1;
  335. /* language is taken from the address */
  336.     if(l>3 && p1[l-3]=='.') {
  337.       for(i=0;i<langcnt;i++) if(strcasecmp(lang[i],p1+l-2)==0) break;
  338.       if(i<langcnt) {p1[l-3]=0; thislang=i;}
  339.       else {/*  unknown language, not referenced */
  340.         continue;
  341.       }
  342.     }
  343.     if(modcnt>0 && strcmp(old,p1)==0 && thislang>=0) {
  344.       if(mod[modcnt-1].langcnt<langcnt) {
  345.         mod[modcnt-1].langs[mod[modcnt-1].langcnt]=thislang;
  346.         mod[modcnt-1].counts[mod[modcnt-1].langcnt]=t;
  347.         (mod[modcnt-1].langcnt)++;
  348.       }
  349.     }
  350.     else {
  351.       mod[modcnt].name=old=p1;
  352.       if(thislang>=0) {
  353.         mod[modcnt].langs[0]=thislang;
  354.         mod[modcnt].langcnt=1;
  355.       }
  356.       else mod[modcnt].langcnt=0;
  357.       mod[modcnt].counts[0]=t;
  358.       modcnt++;
  359.     }
  360.   }
  361.   snprintf(buf,sizeof(buf),"%s/language",outdir);
  362.   langf=fopen(buf,"w");
  363.   snprintf(buf,sizeof(buf),"%s/title",outdir);
  364.   titf=fopen(buf,"w");
  365.   snprintf(buf,sizeof(buf),"%s/description",outdir);
  366.   descf=fopen(buf,"w");
  367.   snprintf(buf,sizeof(buf),"%s/author",outdir);
  368.   authorf=fopen(buf,"w");
  369.   snprintf(buf,sizeof(buf),"%s/version",outdir);
  370.   versionf=fopen(buf,"w");
  371.   snprintf(buf,sizeof(buf),"%s/%s/robot.phtml",outdir,mlistbase);
  372.   robotf=fopen(buf,"w");
  373.   fclose(addrf); fclose(serialf);
  374.   if(!robotf || !versionf || !authorf || !descf || !titf || !langf) {
  375.     fprintf(stderr,"modind: error creating output files.\n");
  376.     exit(1);
  377.   }
  378. }
  379.  
  380. void sprep(void)
  381. {
  382.   char buf[MAX_LINELEN+1];
  383.   char *p1,*p2,*s;
  384.   int i,l,t,thislang;
  385.  
  386.   modcnt=0;
  387.   snprintf(buf,sizeof(buf),"%s/addr",sheetoutdir);
  388.   addrf=fopen(buf,"w");
  389.   if(!addrf) { fprintf(stderr,"modind: error creating output files addr.\n"); exit(1);}
  390.   snprintf(buf,sizeof(buf),"%s/serial",sheetoutdir);
  391.   serialf=fopen(buf,"w");
  392.   s=getenv("slist"); if(s==NULL) return;
  393.   l=strlen(s); if(l<0 || l>100*MAX_LINELEN) return;
  394.   mlist=xmalloc(l+16); ovlstrcpy(mlist,s);
  395.   for(t=0,p1=find_word_start(mlist); *p1 && modcnt<MAX_MODULES; p1=find_word_start(p2),t++) {
  396.     p2=find_word_end(p1);
  397.     l=p2-p1; if(*p2) *p2++=0;
  398.     for(i=0;i<langcnt;i++) if(strncasecmp(lang[i],p1,2)==0) break;
  399.     if(i<langcnt) thislang=i; else continue;
  400.     ovlstrcpy(revmod[t].name,p1);
  401.     revmod[t].lang=thislang;
  402.     mod[modcnt].name=p1;
  403.     mod[modcnt].langs[0]=thislang;
  404.     mod[modcnt].langcnt=1;
  405.     revmod[t].imod=modcnt;
  406.     modcnt++;
  407.     fprintf(addrf,"%d:%s\n",modcnt,p1);
  408.     fprintf(serialf,"%s:%d\n",p1,modcnt);
  409.   }
  410.  fclose(addrf); fclose(serialf);
  411. }
  412.  
  413. void gprep(void)
  414. {
  415.   char buf[MAX_LINELEN+1];
  416.   char *p1,*p2,*s,*old;
  417.   int l,i,t,thislang;
  418.   modcnt=0; old="";
  419.   snprintf(buf,sizeof(buf),"%s/addr",glossaryoutdir);
  420.   addrf=fopen(buf,"w");
  421.   if(!addrf) { fprintf(stderr,"modind: error creating output files addr.\n"); exit(1);}
  422.   snprintf(buf,sizeof(buf),"%s/serial",glossaryoutdir);
  423.   serialf=fopen(buf,"w");
  424.   s=getenv("glist"); if(s==NULL) return;
  425.   l=strlen(s); if(l<0 || l>100*MAX_LINELEN) return;
  426.   mlist=xmalloc(l+16); ovlstrcpy(mlist,s);
  427.   for(t=0,p1=find_word_start(mlist); *p1 && modcnt<MAX_MODULES; p1=find_word_start(p2),t++) {
  428.     p2=find_word_end(p1);
  429.     if(*p2) *p2++=0;
  430.     fprintf(addrf,"%d:%s\n",t,p1);
  431.     fprintf(serialf,"%s:%d\n",p1,t);
  432.     ovlstrcpy(revmod[t].name,p1);
  433.     s=strchr(p1,'/');
  434.     if(s != NULL) s=strchr(s+1,'/');
  435.     if(s==NULL) {
  436.       fprintf(stderr,"modind: no language %s\n",p1); exit(1);
  437.     }
  438.     s++;
  439.     for(i=0;i<langcnt;i++) if(strncasecmp(lang[i],s,2)==0) break;
  440.     thislang = i<langcnt ? i : -1;
  441.     revmod[t].lang=i;
  442.     s[0]=s[1]='x';
  443.     if(modcnt>0 && strcmp(old,p1)==0 && thislang >= 0) {
  444.       if(mod[modcnt-1].langcnt<langcnt) {
  445.         mod[modcnt-1].langs[mod[modcnt-1].langcnt]=thislang;
  446.         mod[modcnt-1].counts[mod[modcnt-1].langcnt]=t;
  447.         (mod[modcnt-1].langcnt)++;
  448.       }
  449.       revmod[t].imod=modcnt-1;
  450.     }
  451.     else {
  452.       mod[modcnt].name=old=p1;
  453.       if(thislang>=0) {
  454.         mod[modcnt].langs[0]=thislang;
  455.         mod[modcnt].langcnt=1;
  456.       }
  457.       else mod[modcnt].langcnt=0;
  458.       mod[modcnt].counts[0]=t;
  459.       revmod[t].imod=modcnt;
  460.       modcnt++;
  461.     }
  462.   }
  463.   fclose(addrf); fclose(serialf);
  464. }
  465.  
  466. /*  read and treat module's INDEX file */
  467. int module_index(const char *name)
  468. {
  469.   char *p, fbuf[MAX_LINELEN+1], ibuf[MAX_LINELEN+1];
  470.   FILE *indf;
  471.   int i,l;
  472.  
  473.   snprintf(fbuf,sizeof(fbuf),"%s/%s/INDEX",moduledir,name);
  474.   indf=fopen(fbuf,"r");
  475.   if(indf==NULL) {
  476.     fprintf(stderr,"modind: INDEX of %s not found\n",fbuf); return -1;
  477.   }
  478.   l=fread(ibuf,1,MAX_LINELEN,indf); fclose(indf);
  479.   if(l>0 && l<MAX_LINELEN) ibuf[l]=0; else return -1;
  480. /* treate all fields in *modindex */
  481.   for(i=0;i<MODINDEX_NO;i++) {
  482.     _getdef(ibuf,modindex[i],indbuf[i]);
  483. /*  compatibility precaution */
  484.     if(indbuf[i][0]==':') indbuf[i][0]='.';
  485.   }
  486.   p=find_word_start(indbuf[i_language]);
  487.   if(isalpha(*p) && isalpha(*(p+1))) {
  488.     memmove(module_language,p,2); module_language[2]=0;
  489.   }
  490.   else ovlstrcpy(module_language,"en");
  491.   return 0;
  492. }
  493.  
  494. int sheet_index(int serial)
  495. {
  496.   char *p1, *p2, fbuf[MAX_LINELEN+1], ibuf[MAX_LINELEN+1];
  497.   FILE *indf;
  498.   int i,l;
  499.  
  500.   snprintf(fbuf,sizeof(fbuf),"%s/%s.def",sheetdir,mod[serial].name);
  501.   indf=fopen(fbuf,"r"); if(indf==NULL) return -1;
  502.   l=fread(ibuf,1,MAX_LINELEN,indf); fclose(indf);
  503.   if(l>0 && l<MAX_LINELEN) ibuf[l]=0; else return -1;
  504.   for(i=0;i<SHEETINDEX_NO;i++) gsindbuf[i][0]=0;
  505.   for(i=0,p1=find_word_start(ibuf);
  506.       i<SHEETINDEX_NO-1 && *p1!=':' && *p1!=0;
  507.       i++,p1=p2) {
  508.     p2=strchr(p1,'\n');
  509.     if(p2!=NULL) *p2++=0; else p2=p1+strlen(p1);
  510.     p1=find_word_start(p1); strip_trailing_spaces2(p1);
  511.     snprintf(gsindbuf[i],MAX_LINELEN,"%s",p1);
  512.   }
  513.   p2=strstr(p1,"\n:"); if(p2==NULL) p2=p1+strlen(p1);
  514.   else *p2=0;
  515.   p1=find_word_start(p1); strip_trailing_spaces2(p1);
  516.   for(p2=p1;*p2;p2++) if(*p2=='\n') *p2=' ';
  517.   ovlstrcpy(gsindbuf[s_information],p1);
  518.   ovlstrcpy(gsindbuf[SHEETINDEX_NO],revmod[serial].name);
  519.   return 0;
  520. }
  521.  
  522. int glossary_index(int serial)
  523. {
  524.   char nbuf[MAX_LINELEN+1],fbuf[MAX_LINELEN+1], ibuf[MAX_LINELEN+1],*p,*s;
  525.   FILE *indf;
  526.   int i,l;
  527.   s=lang[revmod[serial].lang];
  528.   p=strchr(nbuf,'/');
  529.   if(p != NULL) p=strchr(p+1,'/');
  530.   if(p != NULL) {p[1]=s[0];p[2]=s[1];}
  531.   snprintf(fbuf,sizeof(fbuf),"%s/%s",glossarydir,revmod[serial].name);
  532.   indf=fopen(fbuf,"r");
  533.   l=fread(ibuf,1,MAX_LINELEN,indf); fclose(indf);
  534.   if(l>0 && l<MAX_LINELEN) ibuf[l]=0; else return -1;
  535.   for(i=0;i<SHEETINDEX_NO;i++) {
  536.     _getdef(ibuf,glindex[i],gsindbuf[i]);
  537.   }
  538.   ovlstrcpy(gsindbuf[SHEETINDEX_NO],nbuf);
  539.   return 0;
  540. }
  541.  
  542. unsigned char categories[16];
  543. char taken[MAX_LINELEN+1];
  544. int catcnt, takenlen, tweight;
  545.  
  546. /* file management for appenditem */
  547. #define MAX_FILES (MAX_LANGS*catno)
  548.  
  549. char *fnames[MAX_FILES];
  550. FILE *files[MAX_FILES];
  551. int open_files;
  552.  
  553. FILE * file_from_list(char *name){
  554.   int i, l = 0, r = open_files;
  555.   while (r>l){
  556.     int m = (l+r)/2;
  557.     int cmp = strcmp(name,fnames[m]);
  558.     if (!cmp) return files[m];
  559.     if (cmp < 0) r = m; else l = m+1;
  560.   }
  561.   for (i=open_files; i > l; i--) {files[i]=files[i-1]; fnames[i]=fnames[i-1];}
  562.   fnames[l] = xmalloc(MAX_FNAME);
  563.   ovlstrcpy(fnames[l],name);
  564.   open_files++;
  565.   return files[l]=fopen(name,"a");
  566. }
  567.  
  568. void appenditem(char *word, int lind, int serial, int weight, char *l)
  569. {
  570.   char nbuf[MAX_LINELEN+1], buf[MAX_LINELEN+1];
  571.   int i, ll;
  572.   char *p;
  573.   FILE *f;
  574.  
  575.   if(!isalnum(*word) || (ll=strlen(word))<2 ||
  576.      wordchr2(taken,word)!=NULL ||
  577.      wordchr2(ignore[lind],word)!=NULL ||
  578.      takenlen>=MAX_LINELEN-ll-16)
  579.     return;
  580.   if(ll==2 && (!isdigit(word[0]) || !isalpha(word[1]))) return;
  581.   for(p=word;*p;p++) if(!isalnum(*p) && *p!=' ') return;
  582.   taken[takenlen++]=' '; taken[takenlen++]=' ';
  583.   ovlstrcpy(taken+takenlen,word);
  584.   takenlen+=ll; tweight+=weight;
  585.   snprintf(buf,sizeof(buf),"%s:%d?%d\n",word,serial,weight);
  586.   for(i=0;i<catcnt;i++) {
  587.     snprintf(nbuf,sizeof(nbuf),"%s/%c.%s",
  588.        outdir,categories[i],lang[lind]);
  589.     f = file_from_list(nbuf);
  590.     if(f!=NULL) {fputs(buf,f);}
  591.   }
  592. }
  593.  
  594. void appenditem1 (char *buf, int lind, int serial, int weight, char *l )
  595. {
  596.   char *p1, *p2 ;
  597.   for(p1=find_word_start(buf); *p1;
  598.     p1=find_word_start(p2)) {
  599.     p2=strchr(p1,',');
  600.     if(p2!=NULL) *p2++=0; else p2=p1+strlen(p1);
  601.     if(strlen(p1)<=0) continue;
  602.     appenditem(p1,lind,serial,weight,module_language);
  603.   }
  604. }
  605. void appenditem2 (char *buf, int lind, int serial, int weight, char *l )
  606. {
  607.   char *p1, *p2 ;
  608.   for(p1=find_word_start(buf);*p1;
  609.       p1=find_word_start(p2)) {
  610.     p2=find_word_end(p1); if(*p2) *p2++=0;
  611.     appenditem(p1,lind,serial,weight,module_language);
  612.   }
  613. }
  614. void onemodule(const char *name, int serial, int lind)
  615. {
  616.   int i;
  617.   unsigned char trlist[]={
  618.   i_title,i_description,i_category,i_domain,i_keywords,
  619.   i_require,i_author,
  620.   i_keywords_ca,i_keywords_en,i_keywords_fr,i_keywords_it,i_keywords_nl,
  621.   i_title_ca,i_title_en,i_title_fr,i_title_it,i_title_nl
  622.   };
  623.   int trcnt=sizeof(trlist)/sizeof(trlist[0]);
  624.   char *p1, *p2, *pp, *q, buf[MAX_LINELEN+1], lbuf[16];
  625.   FILE *f;
  626.  
  627.   if(module_index(name)) return;
  628.   towords(indbuf[i_category]);
  629. /*   list the categories (among A=all,X=eXercise,O,D,...) corresponding
  630.  *   to this module
  631.  */
  632.   for(i=catcnt=0;i<catno && catcnt<16;i++) {
  633.     if(wordchr2(indbuf[i_category],cat[i].name)!=NULL)
  634.       categories[catcnt++]=cat[i].typ;
  635.   }
  636.   if(catcnt==0) return;
  637.   if(categories[0]!=cat[0].typ)
  638.     categories[catcnt++]=cat[0].typ;
  639. /*  write module's name in the category.language files, for instance lists/X.fr
  640.  * for french exercises
  641.  */
  642.   for(i=0;i<catcnt;i++) {
  643.     snprintf(buf,sizeof(buf),"%s/%s/%c.%s",
  644.        outdir,mlistbase,categories[i],lang[lind]);
  645.     f=fopen(buf,"a");
  646.     if(f!=NULL) {fprintf(f,"%s\n",name); fclose(f);}
  647.   }
  648. /*   add serial number and language (resp.title, ...) to corresponding file  */
  649.   fprintf(langf,"%d:%s\n",serial,module_language);
  650.   fprintf(titf,"%d:%s\n",serial,indbuf[i_title]);
  651.   fprintf(descf,"%d:%s\n",serial,indbuf[i_description]);
  652.   fprintf(authorf,"%d:%s\n",serial,indbuf[i_author]);
  653.   fprintf(versionf,"%d:%s\n",serial,indbuf[i_version]);
  654.  
  655. /*   add module's information in html page for robots  */
  656.   snprintf(buf,sizeof(buf),"%s",indbuf[i_description]);
  657.   for(pp=strchr(buf,','); pp; pp=strchr(pp,','))
  658.     string_modify3(buf,pp,pp+1,"&#44;");
  659.   if(strcmp(module_language,lang[lind])==0)
  660.     fprintf(robotf,"%s ,%s,%s,%s,%s\n",name,module_language,name,
  661.         indbuf[i_title], buf);
  662.  
  663. /*   Normalize the information of trlist, using dictionary
  664.  *  -- bases/sys/domain.xx without suffix translation (--> english version)
  665.  */
  666.   entrycount=dentrycount; dicbuf=ddicbuf;
  667.   memmove(entry,dentry,dentrycount*sizeof(entry[0]));
  668.   unknown_type=unk_leave;
  669.   for(i=0;i<trcnt;i++) {
  670.     detag(indbuf[trlist[i]]);
  671.     deaccent2(indbuf[trlist[i]]);
  672.     comma(indbuf[trlist[i]]);
  673.     singlespace2(indbuf[trlist[i]]);
  674.     translate(indbuf[trlist[i]]);
  675.   }
  676. /*   Normalize the information, using dictionary
  677.  *   bases/sys/words.xx with suffix translation
  678.  */
  679.   entrycount=mentrycount; dicbuf=mdicbuf;
  680.   memmove(entry,mentry,mentrycount*sizeof(entry[0]));
  681.   unknown_type=unk_leave;/*  used in translator_.c */
  682.   for(i=0;i<trcnt;i++) {
  683.   suffix_translate(indbuf[trlist[i]]);
  684.   translate(indbuf[trlist[i]]);
  685.   }
  686.  
  687. /* taken contains all words already seen in the module index */
  688.   taken[0]=0; takenlen=tweight=0;
  689. /*  append words of title  */
  690.   ovlstrcpy(buf,indbuf[i_title]); towords(buf);
  691.   appenditem2(buf,lind,serial,4,module_language);
  692.  
  693. /*  extract words of every other information except level */
  694.   snprintf(buf,sizeof(buf),"%s %s %s %s %s %s %s %s %s %s %s %s %s %s %s",
  695.     indbuf[i_description],indbuf[i_keywords],
  696.     indbuf[i_keywords_ca],indbuf[i_keywords_en],indbuf[i_keywords_fr],
  697.     indbuf[i_keywords_it],indbuf[i_keywords_nl],
  698.     indbuf[i_title_ca],indbuf[i_title_en],indbuf[i_title_fr],
  699.     indbuf[i_title_it],indbuf[i_title_nl],
  700.     indbuf[i_domain],indbuf[i_require],indbuf[i_author]);
  701.   towords(buf);
  702.   appenditem2(buf,lind,serial,2,module_language);
  703.  
  704. /*   this time the dictionary is the group dictionary  sys/wgrp/wgrp
  705.  *   with a g (groupdic), not an m (maindic) . see below main, suffix, group.
  706.  *   and delete unknown ?? and translate
  707.  */
  708.   entrycount=gentrycount; dicbuf=gdicbuf;
  709.   memmove(entry,gentry,gentrycount*sizeof(entry[0]));
  710.  
  711. /* append words of every title information  */
  712.   ovlstrcpy(buf,indbuf[i_title]);
  713.   unknown_type=unk_delete;
  714.   translate(buf);
  715.   appenditem1(buf,lind,serial,2,module_language);
  716.  
  717. /* append words of information of description except level  */
  718.   snprintf(buf,sizeof(buf),"%s", indbuf[i_description]);
  719.   unknown_type=unk_delete;
  720.   translate(buf);
  721.   appenditem1(buf,lind,serial,4,module_language);
  722.  
  723. /* append words (or group of words) of keywords and domain  */
  724.   snprintf(buf,sizeof(buf),"%s, %s, %s, %s, %s, %s, %s",
  725.     indbuf[i_domain],indbuf[i_keywords],
  726.     indbuf[i_keywords_ca], indbuf[i_keywords_en],indbuf[i_keywords_fr],
  727.     indbuf[i_keywords_it], indbuf[i_keywords_nl]);
  728.   unknown_type=unk_leave;
  729.   translate(buf);
  730.   appenditem1(buf,lind,serial,2,module_language);
  731.  
  732. /* append level information, with weight 2 */
  733.   snprintf(buf,sizeof(buf),"%s",indbuf[i_level]);
  734.   ovlstrcpy(lbuf,"level");
  735.   for(p1=buf; *p1; p1++) if(!isalnum(*p1)) *p1=' ';
  736.   q=buf+strlen(buf);
  737.   for(p1=find_word_start(buf); (*p1) && (p1 < q) ; p1=find_word_start(p2)) {
  738.     p2=find_word_end(p1);
  739.     if(p2!=NULL) *p2++=0; else p2=p1+strlen(p1);
  740.     if(strncmp(p1, "Lang" , p2-p1) &&
  741.      (!isalpha(*p1) ||
  742.      (!isdigit(*(p1+1)) && *(p1+1)!=0) ||
  743.      (*(p1+1)!=0 && *(p1+2)!=0)))
  744.        continue;
  745.     *p1=tolower(*p1);
  746.     ovlstrcpy(lbuf+strlen("level"),p1);
  747.     appenditem(lbuf,lind,serial,2,module_language);
  748.   }
  749. /*   append total weight of module to weight file site2/weight.xx  */
  750.   fprintf(weightf,"%d:%d\n",serial,tweight);
  751. }
  752.  
  753. void modules(void)
  754. {
  755.   int i,j,k,d;
  756.   char namebuf[MAX_LINELEN+1];
  757.   char mdic[MAX_LINELEN+1], sdic[MAX_LINELEN+1], gdic[MAX_LINELEN+1], ddic[MAX_LINELEN+1];
  758.  
  759.   for(j=0;j<langcnt;j++) {
  760.     snprintf(namebuf,sizeof(namebuf),"%s/weight.%s",outdir,lang[j]);
  761.     weightf=fopen(namebuf,"w");
  762.     snprintf(mdic,sizeof(mdic),"%s/%s.%s",dicdir,maindic,lang[j]);
  763.     snprintf(sdic,sizeof(sdic),"%s/%s.%s",dicdir,suffixdic,lang[j]);
  764.     snprintf(gdic,sizeof(gdic),"%s/%s.%s",dicdir,groupdic,lang[j]);
  765.     snprintf(ddic,sizeof(ddic),"%s/%s.%s",dicdir,domaindic,lang[j]);
  766.     suffix_dic(sdic); prepare_dic(gdic);
  767.     gdicbuf=dicbuf; gentrycount=entrycount;
  768.     memmove(gentry,entry,gentrycount*sizeof(entry[0]));
  769.     prepare_dic(mdic);
  770.     mdicbuf=dicbuf; mentrycount=entrycount;
  771.     memmove(mentry,entry,mentrycount*sizeof(entry[0]));
  772.     prepare_dic(ddic);
  773.     ddicbuf=dicbuf; dentrycount=entrycount;
  774.     memmove(dentry,entry,dentrycount*sizeof(entry[0]));
  775.     unknown_type=unk_leave; translate(ignore[j]);
  776.     for(i=0;i<modcnt;i++) {
  777.       if(mod[i].langcnt>0) {
  778.       /* look for another language */
  779.         for(d=k=0;k<mod[i].langcnt;k++)
  780.           if(mod[i].langs[k]<mod[i].langs[d]) d=k;
  781.         for(k=0;k<mod[i].langcnt && mod[i].langs[k]!=j;k++);
  782.         if(k>=mod[i].langcnt) k=d;
  783.         snprintf(namebuf,MAX_LINELEN,"%s.%s",mod[i].name,
  784.            lang[mod[i].langs[k]]);
  785.         onemodule(namebuf,mod[i].counts[k],j);
  786.       }
  787.       else {
  788.         onemodule(mod[i].name,mod[i].counts[0],j);
  789.       }
  790.     }
  791.     if(mentrycount>0) free(mdicbuf);
  792.     if(gentrycount>0) free(gdicbuf);
  793.     if(suffixcnt>0) free(sufbuf);
  794.     if(dentrycount>0) free(ddicbuf);
  795.     if(weightf) fclose(weightf);
  796.   }
  797. }
  798. void clean(void)
  799. {
  800.   int i;
  801.   for (i = 0; i < open_files; i++) fclose(files[i]);
  802.   fclose(langf); fclose(titf); fclose(descf); fclose(robotf);
  803.   fclose(authorf); fclose(versionf);
  804. }
  805.  
  806. /* FIXME ? differences with appenditem - use fprintf instead of  snprintf */
  807. void sappenditem(char *word, int lind, int serial, int weight)
  808. {
  809.   int ll;
  810.   char *p;
  811.  
  812.   if(!isalnum(*word) || (ll=strlen(word))<2 ||
  813.      wordchr2(taken,word)!=NULL ||
  814.      wordchr2(ignore[lind],word)!=NULL ||
  815.      takenlen>=MAX_LINELEN-ll-16)
  816.     return;
  817.   if(ll==2 && (!isdigit(word[0]) || !isalpha(word[1]))) return;
  818.   for(p=word;*p;p++) if(!isalnum(*p) && *p!=' ') return;
  819.   taken[takenlen++]=' ';taken[takenlen++]=' ';
  820.   ovlstrcpy(taken+takenlen,word);
  821.   takenlen+=ll; tweight+=weight;
  822.   fprintf(indf,"%s:%d?%d\n",word,serial,weight);
  823. }
  824. /* onesg / onemodule are similar */
  825. void onesg(int serial, int lind, int index(int))
  826. {
  827.   int i;
  828.   unsigned char trlist[]={
  829.     s_title,s_description,s_domain,s_keywords,s_information
  830.   };
  831.   int trcnt=sizeof(trlist)/sizeof(trlist[0]);
  832.   char *p1, *p2, *q, buf[MAX_LINELEN+1], lbuf[16];
  833.  
  834.   if(index(serial)) return;
  835.   fprintf(titf,"%d:%s\n",serial,gsindbuf[s_title]);
  836.   fprintf(descf,"%d:%s\n",serial,gsindbuf[s_description]);
  837.   fprintf(remf,"%d:%s\n",serial,gsindbuf[s_information]);
  838.  
  839. /*   Normalize the information of trlist, using dictionary
  840.  *  -- bases/sys/domain.xx without suffix translation (--> english version)
  841.  */
  842.   entrycount=dentrycount; dicbuf=ddicbuf;
  843.   memmove(entry,dentry,dentrycount*sizeof(entry[0]));
  844.   unknown_type=unk_leave;
  845.   for(i=0;i<trcnt;i++) {
  846.     detag(gsindbuf[trlist[i]]);
  847.     deaccent2(gsindbuf[trlist[i]]);
  848.     comma(gsindbuf[trlist[i]]);
  849.     singlespace2(gsindbuf[trlist[i]]);
  850.     translate(gsindbuf[trlist[i]]);
  851.   }
  852. /*   Normalize the information, using dictionary
  853.  *   bases/sys/words.xx with suffix translation
  854.  */
  855.   entrycount=mentrycount; dicbuf=mdicbuf;
  856.   memmove(entry,mentry,mentrycount*sizeof(entry[0]));
  857.   unknown_type=unk_leave;/*  used in translator_.c */
  858.   for(i=0;i<trcnt;i++) {
  859.     suffix_translate(gsindbuf[trlist[i]]);
  860.     translate(gsindbuf[trlist[i]]);
  861.   }
  862.  
  863. /* taken contains all words already seen in the module index */
  864.   taken[0]=0; takenlen=tweight=0;
  865. /*  append words of title  */
  866.   ovlstrcpy(buf,gsindbuf[s_title]); towords(buf);
  867.   for(p1=find_word_start(buf);*p1;
  868.       p1=find_word_start(p2)) {
  869.     p2=find_word_end(p1); if(*p2) *p2++=0;
  870.     sappenditem(p1,lind,serial,4);
  871.   }
  872.  
  873. /*  extract words of every other information except level */
  874.   snprintf(buf,sizeof(buf),"%s %s %s %s",
  875.          gsindbuf[s_description],gsindbuf[s_keywords],
  876.          gsindbuf[s_domain],gsindbuf[s_information]);
  877.   towords(buf);
  878.   for(p1=find_word_start(buf);*p1;p1=find_word_start(p2)) {
  879.     p2=find_word_end(p1); if(*p2) *p2++=0;
  880.     sappenditem(p1,lind,serial,2);
  881.   }
  882. /*   this time the dictionary is the group dictionary  sys/wgrp/wgrp
  883.  *   with a g (groupdic), not an m (maindic) . see below main, suffix, group.
  884.  *   and delete unknown ?? and translate
  885.  */
  886.   entrycount=gentrycount; dicbuf=gdicbuf;
  887.   memmove(entry,gentry,gentrycount*sizeof(entry[0]));
  888.  
  889. /*  append words of every title information  */
  890.   ovlstrcpy(buf,gsindbuf[s_title]);
  891.   unknown_type=unk_delete;
  892.   translate(buf);
  893.   for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) {
  894.     p2=strchr(p1,',');
  895.     if(p2!=NULL) *p2++=0; else p2=p1+strlen(p1);
  896.     if(strlen(p1)<=0) continue;
  897.     sappenditem(p1,lind,serial,4);
  898.   }
  899.  
  900. /*  append words (or group of words) of keywords and domain  */
  901.   snprintf(buf,sizeof(buf),"%s, %s",
  902.        gsindbuf[s_keywords],
  903.        gsindbuf[s_domain]);
  904.   unknown_type=unk_leave;
  905.   translate(buf);
  906.   for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) {
  907.     p2=strchr(p1,',');
  908.     if(p2!=NULL) *p2++=0; else p2=p1+strlen(p1);
  909.     if(strlen(p1)<=0) continue;
  910.     sappenditem(p1,lind,serial,2);
  911.   }
  912.  
  913. /*   append level information, with weight 2 */
  914.   snprintf(buf,sizeof(buf),"%s",gsindbuf[s_level]);
  915.   ovlstrcpy(lbuf,"level");
  916.   for(p1=buf; *p1; p1++) if(!isalnum(*p1)) *p1=' ';
  917.   q=buf+strlen(buf);
  918.   for(p1=find_word_start(buf); (*p1) && (p1 < q) ;
  919.   p1=find_word_start(p2)) {
  920.     p2=find_word_end(p1);
  921.     if(p2!=NULL) *p2++=0; else p2=p1+strlen(p1);
  922.     if(strncmp(p1, "Lang" , p2-p1) &&
  923.         (!isalpha(*p1) || (!isdigit(*(p1+1))) ||
  924.         (*(p1+1)!=0 && *(p1+2)!=0)))
  925.       continue;
  926.     *p1=tolower(*p1);
  927.     ovlstrcpy(lbuf+strlen("level"),p1);
  928.     sappenditem(lbuf,lind,serial,2);
  929.   }
  930. /*   append total weight of module to weight file site2/weight.xx  */
  931.   fprintf(weightf,"%d:%d\n",serial,tweight);
  932. }
  933.  
  934. void sgs(char *outdir, int index(int))
  935. {
  936.   int i,j,k,d;
  937.   char mdic[MAX_LINELEN+1], sdic[MAX_LINELEN+1], gdic[MAX_LINELEN+1], ddic[MAX_LINELEN+1];
  938.   char buf[MAX_LINELEN+1];
  939.  
  940.   //snprintf(buf,sizeof(buf),"%s/list",outdir);
  941.   //listf=fopen(buf,"w");
  942.   snprintf(buf,sizeof(buf),"%s/title",outdir);
  943.   titf=fopen(buf,"w");
  944.   snprintf(buf,sizeof(buf),"%s/description",outdir);
  945.   descf=fopen(buf,"w");
  946.   snprintf(buf,sizeof(buf),"%s/information",outdir);
  947.   remf=fopen(buf,"w");
  948.   if(!remf || !descf || !titf ) {
  949.     fprintf(stderr,"modind: error creating output files for %s.\n",outdir); exit(1);
  950.   }
  951.   for(j=0;j<langcnt;j++) {
  952.     snprintf(buf,sizeof(buf),"%s/%s",outdir,lang[j]);
  953.     indf=fopen(buf,"w");
  954.     snprintf(buf,sizeof(buf),"%s/weight.%s",outdir,lang[j]);
  955.     weightf=fopen(buf,"w");
  956.     if(!weightf || !indf ) {
  957.       fprintf(stderr,"modind: error creating output files for %s.\n",outdir); exit(1);
  958.     }
  959.     snprintf(mdic,sizeof(mdic),"%s/%s.%s",dicdir,maindic,lang[j]);
  960.     snprintf(sdic,sizeof(sdic),"%s/%s.%s",dicdir,suffixdic,lang[j]);
  961.     snprintf(gdic,sizeof(gdic),"%s/%s.%s",dicdir,groupdic,lang[j]);
  962.     snprintf(ddic,sizeof(ddic),"%s/%s.%s",dicdir,domaindic,lang[j]);
  963.     suffix_dic(sdic); prepare_dic(gdic);
  964.     gdicbuf=dicbuf; gentrycount=entrycount;
  965.     memmove(gentry,entry,gentrycount*sizeof(entry[0]));
  966.     prepare_dic(mdic);
  967.     mdicbuf=dicbuf; mentrycount=entrycount;
  968.     memmove(mentry,entry,mentrycount*sizeof(entry[0]));
  969.     prepare_dic(ddic);
  970.     ddicbuf=dicbuf; dentrycount=entrycount;
  971.     memmove(dentry,entry,dentrycount*sizeof(entry[0]));
  972.     unknown_type=unk_leave; translate(ignore[j]);
  973.     for(i=0;i<modcnt;i++)
  974.       if(mod[i].langcnt>0) {
  975.       /* look for another language */
  976.         for(d=k=0;k<mod[i].langcnt;k++)
  977.           if(mod[i].langs[k]<mod[i].langs[d]) d=k;
  978.         for(k=0;k<mod[i].langcnt && mod[i].langs[k]!=j;k++);
  979.         if(k>=mod[i].langcnt) k=d;
  980.         onesg(mod[i].counts[k],mod[i].langs[k],index);
  981.       }
  982.     if(mentrycount>0) free(mdicbuf);
  983.     if(gentrycount>0) free(gdicbuf);
  984.     if(suffixcnt>0) free(sufbuf);
  985.     if(dentrycount>0) free(ddicbuf);
  986.     fclose(indf); fclose(weightf);
  987.   }
  988.   fclose(titf); fclose(descf); fclose(remf);
  989. }
  990.  
  991. int main()
  992. {
  993.   gentry=xmalloc(entry_size);
  994.   dentry=xmalloc(entry_size);
  995.   mentry=xmalloc(entry_size);
  996.   init();
  997.   prep();
  998.   if(modcnt>0) modules();
  999.   clean();
  1000.   sprep();
  1001.   if(modcnt>0) sgs(sheetoutdir,sheet_index);
  1002.   gprep();
  1003.   if(modcnt>0) sgs(glossaryoutdir,glossary_index);
  1004.   return 0;
  1005. }
  1006.