~ubuntu-branches/ubuntu/lucid/dict-ns/lucid

« back to all changes in this revision

Viewing changes to utils/munch.c

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-02-06 20:11:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070206201142-vix5rf0kn1h06h94
Tags: upstream-20070206
ImportĀ upstreamĀ versionĀ 20070206

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Munch a word list and generate a smaller root word list with affixes*/
 
2
 
 
3
#include <ctype.h>
 
4
#include <string.h>
 
5
#include <unistd.h>
 
6
#include <stdlib.h>
 
7
#include <stdio.h>
 
8
#include <sys/types.h>
 
9
#include <sys/stat.h>
 
10
#include <fcntl.h>
 
11
#ifdef __linux__
 
12
#include <error.h>
 
13
#include <errno.h>
 
14
#endif
 
15
#include <sys/mman.h>
 
16
 
 
17
#include "munch.h"
 
18
 
 
19
int main(int argc, char** argv)
 
20
{
 
21
 
 
22
  int i, j, k, n;
 
23
  int rl, p , nwl;
 
24
  int al;
 
25
 
 
26
  FILE * wrdlst;
 
27
  FILE * afflst;
 
28
 
 
29
  char *nword, *wf, *af;
 
30
  char as[(MAX_PREFIXES + MAX_SUFFIXES)];
 
31
  char * ap;
 
32
 
 
33
  struct hentry * ep;
 
34
  struct hentry * ep1;
 
35
  struct affent * pfxp;
 
36
  struct affent * sfxp;
 
37
 
 
38
  /* first parse the command line options */
 
39
  /* arg1 - wordlist, arg2 - affix file */
 
40
 
 
41
  if (argv[1]) {
 
42
       wf = mystrdup(argv[1]);
 
43
  } else {
 
44
    fprintf(stderr,"correct syntax is:\n"); 
 
45
    fprintf(stderr,"munch word_list_file affix_file\n");
 
46
    exit(1);
 
47
  }
 
48
  if (argv[2]) {
 
49
       af = mystrdup(argv[2]);
 
50
  } else {
 
51
    fprintf(stderr,"correct syntax is:\n"); 
 
52
    fprintf(stderr,"munch word_list_file affix_file\n");
 
53
    exit(1);
 
54
  }
 
55
 
 
56
  /* open the affix file */
 
57
  afflst = fopen(af,"r");
 
58
  if (!afflst) {
 
59
    fprintf(stderr,"Error - could not open affix description file\n");
 
60
    exit(1);
 
61
  }
 
62
 
 
63
  /* step one is to parse the affix file building up the internal
 
64
     affix data structures */
 
65
 
 
66
  numpfx = 0;
 
67
  numsfx = 0;
 
68
 
 
69
  parse_aff_file(afflst);
 
70
  fclose(afflst);
 
71
 
 
72
  fprintf(stderr,"parsed in %d prefixes and %d suffixes\n",numpfx,numsfx);
 
73
 
 
74
  /* affix file is now parsed so create hash table of wordlist on the fly */
 
75
 
 
76
  /* open the wordlist */
 
77
  wrdlst = fopen(wf,"r");
 
78
  if (!wrdlst) {
 
79
    fprintf(stderr,"Error - could not open word list file\n");
 
80
    exit(1);
 
81
  }
 
82
 
 
83
  if (load_tables(wrdlst)) {
 
84
    fprintf(stderr,"Error building hash tables\n");
 
85
    exit(1);
 
86
  }
 
87
  fclose(wrdlst);
 
88
 
 
89
  for (i=0; i< tablesize; i++) {
 
90
    ep = &tableptr[i];
 
91
    if (ep->word == NULL) continue;
 
92
    for (  ;  ep != NULL;  ep = ep->next) {
 
93
      numroots = 0;
 
94
      aff_chk(ep->word,strlen(ep->word));
 
95
      if (numroots) {
 
96
            /* now there might be a number of combinations */
 
97
            /* of prefixes and suffixes that might match this */
 
98
            /* word.  So how to choose?  As a first shot look */
 
99
            /* for the shortest remaining root word to */
 
100
            /* to maximize the combinatorial power */
 
101
 
 
102
            /* but be careful, do not REQUIRE a specific combination */
 
103
            /* of a prefix and a suffix to generate the word since */
 
104
            /* that violates the rule that the root word with just */
 
105
            /* the prefix or just the suffix must also exist in the */
 
106
            /* wordlist as well */
 
107
 
 
108
            /* in fact because of the cross product issue, this not a  */
 
109
            /* simple choice since some combinations of previous */ 
 
110
            /* prefixes and new suffixes may not be valid. */
 
111
            /*  The only way to know is to simply try them all */
 
112
  
 
113
            rl = 1000;
 
114
            p = -1;
 
115
 
 
116
            for (j = 0; j < numroots; j++){
 
117
 
 
118
              /* first collect the root word info and build up */
 
119
              /* the potential new affix string */
 
120
               nword = (roots[j].hashent)->word;
 
121
               nwl = strlen(nword);
 
122
               *as = '\0';
 
123
               al = 0;
 
124
               ap = as;
 
125
               if (roots[j].prefix) *ap++ = (roots[j].prefix)->achar;
 
126
               if (roots[j].suffix) *ap++ = (roots[j].suffix)->achar;
 
127
               if ((roots[j].hashent)->affstr) {
 
128
                   strcpy(ap,(roots[j].hashent)->affstr);
 
129
               } else {
 
130
                 *ap = '\0';
 
131
               }
 
132
               al =strlen(as);
 
133
 
 
134
               /* now expand the potential affix string to generate */
 
135
               /* all legal words and make sure they all exist in the */
 
136
               /* word list */
 
137
               numwords = 0;
 
138
               wlist[numwords].word = mystrdup(nword);
 
139
               wlist[numwords].pallow = 0;
 
140
               numwords++;
 
141
               n = 0;
 
142
               if (al)
 
143
                 expand_rootword(nword,nwl,as,al);
 
144
               for (k=0; k<numwords; k++) {
 
145
                 if (lookup(wlist[k].word)) n++;
 
146
                 free(wlist[k].word);
 
147
                 wlist[k].word = NULL;
 
148
                 wlist[k].pallow = 0;
 
149
               }
 
150
 
 
151
               /* if all exist in word list then okay */
 
152
               if (n == numwords) {               
 
153
                  if (nwl < rl) {
 
154
                     rl = nwl;
 
155
                     p = j;
 
156
                  }
 
157
               }
 
158
            }
 
159
            if (p != -1) {
 
160
               ep1 = roots[p].hashent;
 
161
               pfxp = roots[p].prefix;
 
162
               sfxp = roots[p].suffix;
 
163
               ep1->keep = 1;
 
164
               if (pfxp != NULL) add_affix_char(ep1,pfxp->achar);
 
165
               if (sfxp != NULL) add_affix_char(ep1,sfxp->achar);
 
166
            } else {
 
167
              ep->keep = 1;
 
168
            }
 
169
      } else {
 
170
            ep->keep = 1;
 
171
      }
 
172
    }
 
173
  }
 
174
 
 
175
  /* now output only the words to keep along with affixes info */
 
176
  /* first count how many words that is */
 
177
  k = 0;
 
178
  for (i=0; i< tablesize; i++) {
 
179
    ep = &tableptr[i];
 
180
    if (ep->word == NULL) continue;
 
181
    for (  ;  ep != NULL;  ep = ep->next) {
 
182
       if (ep->keep > 0) k++;
 
183
    }
 
184
  }
 
185
  fprintf(stdout,"%d\n",k);
 
186
 
 
187
  for (i=0; i< tablesize; i++) {
 
188
    ep = &tableptr[i];
 
189
    if (ep->word == NULL) continue;
 
190
    for (  ;  ep != NULL;  ep = ep->next) {
 
191
      if (ep->keep > 0) {
 
192
        if (ep->affstr != NULL) { 
 
193
          fprintf(stdout,"%s/%s\n",ep->word,ep->affstr);
 
194
        } else {
 
195
          fprintf(stdout,"%s\n",ep->word);
 
196
        }
 
197
      }
 
198
    }
 
199
  }
 
200
  return 0;
 
201
}
 
202
 
 
203
 
 
204
void parse_aff_file(FILE * afflst)
 
205
{  
 
206
    int i, j;
 
207
    int numents = 0;
 
208
    char achar = '\0';
 
209
    short ff=0;
 
210
    char ft;
 
211
    struct affent * ptr= NULL;
 
212
    struct affent * nptr= NULL;
 
213
    char * line = malloc(MAX_LN_LEN);
 
214
 
 
215
    while (fgets(line,MAX_LN_LEN,afflst)) {
 
216
       mychomp(line);
 
217
       ft = ' ';
 
218
       fprintf(stderr,"parsing line: %s\n",line);
 
219
       if (strncmp(line,"PFX",3) == 0) ft = 'P';
 
220
       if (strncmp(line,"SFX",3) == 0) ft = 'S';
 
221
       if (ft != ' ') {
 
222
          char * tp = line;
 
223
          char * piece;
 
224
          i = 0;
 
225
          ff = 0;
 
226
          while ((piece=mystrsep(&tp,' '))) {
 
227
             if (*piece != '\0') {
 
228
                 switch(i) {
 
229
                    case 0: break;
 
230
                    case 1: { achar = *piece; break; }
 
231
                    case 2: { if (*piece == 'Y') ff = XPRODUCT; break; }
 
232
                    case 3: { numents = atoi(piece); 
 
233
                              ptr = malloc(numents * sizeof(struct affent));
 
234
                              ptr->achar = achar;
 
235
                              ptr->xpflg = ff;
 
236
                              fprintf(stderr,"parsing %c entries %d\n",achar,numents);
 
237
                              break;
 
238
                            }
 
239
                    default: break;
 
240
                 }
 
241
                 i++;
 
242
             }
 
243
             free(piece);
 
244
          }
 
245
          /* now parse all of the sub entries*/
 
246
          nptr = ptr;
 
247
          for (j=0; j < numents; j++) {
 
248
             fgets(line,MAX_LN_LEN,afflst);
 
249
             mychomp(line);
 
250
             tp = line;
 
251
             i = 0;
 
252
             while ((piece=mystrsep(&tp,' '))) {
 
253
                if (*piece != '\0') {
 
254
                    switch(i) {
 
255
                       case 0: { if (nptr != ptr) {
 
256
                                   nptr->achar = ptr->achar;
 
257
                                   nptr->xpflg = ptr->xpflg;
 
258
                                 }
 
259
                                 break;
 
260
                               }
 
261
                       case 1: break;
 
262
                       case 2: { nptr->strip = mystrdup(piece);
 
263
                                 nptr->stripl = strlen(nptr->strip);
 
264
                                 if (strcmp(nptr->strip,"0") == 0) {
 
265
                                   free(nptr->strip);
 
266
                                   nptr->strip=mystrdup("");
 
267
                                   nptr->stripl = 0;
 
268
                                 }   
 
269
                                 break; 
 
270
                               }
 
271
                       case 3: { nptr->appnd = mystrdup(piece);
 
272
                                 nptr->appndl = strlen(nptr->appnd);
 
273
                                 if (strcmp(nptr->appnd,"0") == 0) {
 
274
                                   free(nptr->appnd);
 
275
                                   nptr->appnd=mystrdup("");
 
276
                                   nptr->appndl = 0;
 
277
                                 }   
 
278
                                 break; 
 
279
                               }
 
280
                       case 4: { encodeit(nptr,piece);}
 
281
                               fprintf(stderr, "   affix: %s %d, strip: %s %d\n",nptr->appnd,
 
282
                                                   nptr->appndl,nptr->strip,nptr->stripl);
 
283
                       default: break;
 
284
                    }
 
285
                    i++;
 
286
                }
 
287
                free(piece);
 
288
             }
 
289
             nptr++;
 
290
          }
 
291
          if (ft == 'P') {
 
292
             ptable[numpfx].aep = ptr;
 
293
             ptable[numpfx].num = numents;
 
294
             fprintf(stderr,"ptable %d num is %d\n",numpfx,ptable[numpfx].num);
 
295
             numpfx++;
 
296
          } else {
 
297
             stable[numsfx].aep = ptr;
 
298
             stable[numsfx].num = numents;
 
299
             fprintf(stderr,"stable %d num is %d\n",numsfx,stable[numsfx].num);
 
300
             numsfx++;
 
301
          }
 
302
          ptr = NULL;
 
303
          nptr = NULL;
 
304
          numents = 0;
 
305
          achar='\0';
 
306
       }
 
307
    }
 
308
    free(line);
 
309
}
 
310
 
 
311
 
 
312
void encodeit(struct affent * ptr, char * cs)
 
313
{
 
314
  int nc;
 
315
  int neg;
 
316
  int grp;
 
317
  unsigned char c;
 
318
  int n;
 
319
  int ec;   
 
320
  int nm;
 
321
  int i, j, k;
 
322
  unsigned char mbr[MAX_WD_LEN];
 
323
 
 
324
  /* now clear the conditions array */
 
325
  for (i=0;i<SET_SIZE;i++) ptr->conds[i] = (unsigned char) 0;
 
326
 
 
327
  /* now parse the string to create the conds array */
 
328
  nc = strlen(cs);
 
329
  neg = 0;  /* complement indicator */
 
330
  grp = 0;  /* group indicator */
 
331
  n = 0;    /* number of conditions */
 
332
  ec = 0;   /* end condition indicator */
 
333
  nm = 0;   /* number of member in group */
 
334
  i = 0;
 
335
  if (strcmp(cs,".")==0) {
 
336
    ptr->numconds = 0;
 
337
    return;
 
338
  }
 
339
  while (i < nc) {
 
340
    c = *((unsigned char *)(cs + i));
 
341
    if (c == '[') {
 
342
       grp = 1;
 
343
       c = 0;
 
344
    }
 
345
    if ((grp == 1) && (c == '^')) {
 
346
       neg = 1;
 
347
       c = 0;
 
348
    }
 
349
    if (c == ']') {
 
350
       ec = 1;
 
351
       c = 0;
 
352
    }
 
353
    if ((grp == 1) && (c != 0)) {
 
354
      *(mbr + nm) = c;
 
355
      nm++;
 
356
      c = 0;
 
357
    }
 
358
    if (c != 0) {
 
359
       ec = 1;
 
360
    }
 
361
    if (ec) {
 
362
      if (grp == 1) {
 
363
        if (neg == 0) {
 
364
          for (j=0;j<nm;j++) {
 
365
             k = (unsigned int) mbr[j];
 
366
             ptr->conds[k] = ptr->conds[k] | (1 << n);
 
367
          }
 
368
        } else {
 
369
           for (j=0;j<SET_SIZE;j++) ptr->conds[j] = ptr->conds[j] | (1 << n);
 
370
           for (j=0;j<nm;j++) {
 
371
             k = (unsigned int) mbr[j];
 
372
             ptr->conds[k] = ptr->conds[k] & ~(1 << n);
 
373
           }
 
374
        }
 
375
        neg = 0;
 
376
        grp = 0;   
 
377
        nm = 0;
 
378
      } else {
 
379
        /* not a group so just set the proper bit for this char */
 
380
        /* but first handle special case of . inside condition */
 
381
        if (c == '.') {
 
382
          /* wild card character so set them all */
 
383
          for (j=0;j<SET_SIZE;j++) ptr->conds[j] = ptr->conds[j] | (1 << n);
 
384
        } else {
 
385
          ptr->conds[(unsigned int) c] = ptr->conds[(unsigned int)c] | (1 << n);
 
386
        }
 
387
      }
 
388
      n++;
 
389
      ec = 0;
 
390
    }
 
391
    i++;
 
392
  }
 
393
  ptr->numconds = n;
 
394
  return;
 
395
}
 
396
 
 
397
 
 
398
 
 
399
/* search for a prefix */
 
400
void pfx_chk (const char * word, int len, struct affent* ep, int num)
 
401
{
 
402
    struct affent *     aent;
 
403
    int                 cond;
 
404
    int tlen;
 
405
    struct hentry *     hent;
 
406
    unsigned char *     cp;             
 
407
    int                 i;
 
408
    char                tword[MAX_WD_LEN];
 
409
 
 
410
    for (aent = ep, i = num; i > 0; aent++, i--) {
 
411
 
 
412
        tlen = len - aent->appndl;
 
413
 
 
414
        if (tlen > 0 &&  (aent->appndl == 0 ||  
 
415
            strncmp(aent->appnd, word, aent->appndl) == 0)
 
416
            &&  tlen + aent->stripl >= aent->numconds) {
 
417
 
 
418
            if (aent->stripl) strcpy (tword, aent->strip);
 
419
            strcpy((tword + aent->stripl), (word + aent->appndl));
 
420
 
 
421
            /* now go through the conds and make sure they all match */
 
422
            cp = (unsigned char *) tword;
 
423
            for (cond = 0;  cond < aent->numconds;  cond++) {
 
424
                if ((aent->conds[*cp++] & (1 << cond)) == 0)
 
425
                    break;
 
426
            }
 
427
 
 
428
            if (cond >= aent->numconds) {
 
429
                tlen += aent->stripl;
 
430
                if ((hent = lookup(tword)) != NULL) {
 
431
                   if (numroots < MAX_ROOTS) {
 
432
                       roots[numroots].hashent = hent;
 
433
                       roots[numroots].prefix = aent;
 
434
                       roots[numroots].suffix = NULL;
 
435
                       numroots++;
 
436
                   }
 
437
                }
 
438
            }
 
439
        }
 
440
    }
 
441
}
 
442
 
 
443
 
 
444
 
 
445
void suf_chk (const char * word, int len, struct affent * ep, 
 
446
              int num, struct affent * pfxent, int cpflag)
 
447
{
 
448
    struct affent *     aent;   
 
449
    int                 tlen;   
 
450
    int                 cond;   
 
451
    struct hentry *     hent;   
 
452
    unsigned char *     cp;
 
453
    int                 i;
 
454
    char                tword[MAX_WD_LEN];
 
455
 
 
456
    for (aent = ep, i = num; i > 0; aent++, i--) {
 
457
 
 
458
        if ((cpflag & XPRODUCT) != 0 &&  (aent->xpflg & XPRODUCT) == 0)
 
459
            continue;
 
460
 
 
461
        tlen = len - aent->appndl;
 
462
        if (tlen > 0  &&  (aent->appndl == 0 ||  
 
463
            strcmp(aent->appnd, (word + tlen)) == 0)
 
464
            &&  tlen + aent->stripl >= aent->numconds) {
 
465
 
 
466
            strcpy (tword, word);
 
467
            cp = (unsigned char *) (tword + tlen);
 
468
            if (aent->stripl) {
 
469
               strcpy ((char *)cp, aent->strip);
 
470
               tlen += aent->stripl;
 
471
               cp = (unsigned char *)(tword + tlen);
 
472
            } else *cp = '\0';
 
473
 
 
474
            for (cond = aent->numconds;  --cond >= 0;  ) {
 
475
                if ((aent->conds[*--cp] & (1 << cond)) == 0) break;
 
476
            }
 
477
            if (cond < 0) {
 
478
               if ((hent = lookup(tword)) != NULL) {
 
479
                  if (numroots < MAX_ROOTS) {
 
480
                     roots[numroots].hashent = hent;
 
481
                     roots[numroots].prefix = pfxent;
 
482
                     roots[numroots].suffix = aent;
 
483
                     numroots++;
 
484
                  }
 
485
               }
 
486
            }
 
487
        }
 
488
    }
 
489
}
 
490
 
 
491
 
 
492
 
 
493
void aff_chk (const char * word, int len)
 
494
{
 
495
    int i;
 
496
    int j;
 
497
    int nh=0;
 
498
    char * nword;
 
499
    int nwl;
 
500
 
 
501
    if (len < 4) return;
 
502
 
 
503
    for (i=0; i < numpfx; i++) {
 
504
       pfx_chk(word, len, ptable[i].aep, ptable[i].num);
 
505
    }
 
506
 
 
507
    nh = numroots;
 
508
 
 
509
    if (nh > 0) {
 
510
       for (j=0;j<nh;j++){
 
511
         if (roots[j].prefix->xpflg & XPRODUCT) {
 
512
            nword = mystrdup((roots[j].hashent)->word);
 
513
            nwl = strlen(nword);
 
514
            for (i=0; i < numsfx; i++) {
 
515
               suf_chk(nword,nwl,stable[i].aep, stable[i].num, roots[j].prefix, XPRODUCT);
 
516
            }
 
517
            free(nword);
 
518
         }
 
519
       }
 
520
    }
 
521
    for (i=0; i < numsfx; i++) {
 
522
       suf_chk(word, len, stable[i].aep, stable[i].num, NULL, 0);
 
523
    }
 
524
}
 
525
 
 
526
 
 
527
 
 
528
/* lookup a root word in the hashtable */
 
529
 
 
530
struct hentry * lookup(const char *word)
 
531
{
 
532
    struct hentry * dp;
 
533
    dp = &tableptr[hash(word)];
 
534
    if (dp->word == NULL) return NULL;
 
535
    for (  ;  dp != NULL;  dp = dp->next) {
 
536
      if (strcmp(word,dp->word) == 0) return dp;
 
537
    }
 
538
    return NULL;
 
539
}
 
540
 
 
541
 
 
542
 
 
543
/* add a word to the hash table */
 
544
 
 
545
int add_word(char * word)
 
546
{
 
547
    int i;
 
548
    struct hentry * dp;
 
549
    struct hentry * hp = (struct hentry *) malloc (sizeof(struct hentry));
 
550
 
 
551
    hp->word = word;
 
552
    hp->affstr = NULL;
 
553
    hp->keep = 0;
 
554
    hp->next = NULL;
 
555
 
 
556
    i = hash(word);
 
557
    dp = &tableptr[i];
 
558
    
 
559
    if (dp->word == NULL) {
 
560
      *dp = *hp;
 
561
       free(hp);
 
562
    } else {
 
563
      while (dp->next != NULL) dp=dp->next; 
 
564
      dp->next = hp;
 
565
    }
 
566
    return 0;
 
567
}     
 
568
 
 
569
 
 
570
 
 
571
/* load a word list and build a hash table on the fly */
 
572
 
 
573
int load_tables(FILE * wdlst)
 
574
{
 
575
  char * ap;
 
576
  char ts[MAX_LN_LEN];
 
577
 
 
578
  /* first read the first line of file to get hash table size */
 
579
  if (! fgets(ts, MAX_LN_LEN-1,wdlst)) return 2;
 
580
  mychomp(ts);
 
581
  tablesize = atoi(ts);
 
582
  tablesize = tablesize + 5;
 
583
  if ((tablesize %2) == 0) tablesize++;
 
584
 
 
585
  /* allocate the hash table */
 
586
  tableptr = (struct hentry *) calloc(tablesize, sizeof(struct hentry));
 
587
  if (! tableptr) return 3;
 
588
 
 
589
  /* loop thorugh all words on much list and add to hash
 
590
   * table and store away word and affix strings in tmpfile
 
591
   */
 
592
 
 
593
  while (fgets(ts,MAX_LN_LEN-1,wdlst)) {
 
594
    mychomp(ts);
 
595
    ap = mystrdup(ts);
 
596
    add_word(ap);
 
597
 
 
598
  }
 
599
  return 0;
 
600
}
 
601
 
 
602
 
 
603
/* the hash function is a simple load and rotate
 
604
 * algorithm borrowed
 
605
 */
 
606
 
 
607
int hash(const char * word)
 
608
{
 
609
    int i;
 
610
    long  hv = 0;
 
611
    for (i=0; i < 4  &&  *word != 0; i++)
 
612
        hv = (hv << 8) | (*word++);
 
613
    while (*word != 0) {
 
614
      ROTATE(hv,ROTATE_LEN);
 
615
      hv ^= (*word++);
 
616
    }
 
617
    return (unsigned long) hv % tablesize;
 
618
}
 
619
 
 
620
 
 
621
void add_affix_char(struct hentry * ep, char ac)
 
622
{
 
623
  int al;
 
624
  int i;
 
625
  char * tmp;
 
626
  if (ep->affstr == NULL) {
 
627
     ep->affstr = (char *) malloc(2*sizeof(char));
 
628
     *(ep->affstr) = ac;
 
629
     *((ep->affstr)+1) = '\0';
 
630
     return;
 
631
  }
 
632
  al = strlen(ep->affstr);
 
633
  for (i=0; i< al; i++)
 
634
    if (ac == (ep->affstr)[i]) return;
 
635
  tmp = calloc((al+2),sizeof(char));
 
636
  memcpy(tmp,ep->affstr,(al+1));
 
637
  *(tmp+al) = ac;
 
638
  *(tmp+al+1)='\0';
 
639
  free(ep->affstr);
 
640
  ep->affstr = tmp;
 
641
  return;
 
642
}
 
643
 
 
644
 
 
645
/* add a prefix to word */
 
646
void pfx_add (const char * word, int len, struct affent* ep, int num)
 
647
{
 
648
    struct affent *     aent;
 
649
    int                 cond;
 
650
    int tlen;
 
651
    unsigned char *     cp;             
 
652
    int                 i;
 
653
    char *              pp;
 
654
    char                tword[MAX_WD_LEN];
 
655
 
 
656
    
 
657
    for (aent = ep, i = num; i > 0; aent++, i--) {
 
658
 
 
659
        /* now make sure all conditions match */
 
660
        if ((len > aent->stripl) && (len >= aent->numconds)) {
 
661
 
 
662
            cp = (unsigned char *) word;
 
663
            for (cond = 0;  cond < aent->numconds;  cond++) {
 
664
               if ((aent->conds[*cp++] & (1 << cond)) == 0)
 
665
                  break;
 
666
            }
 
667
            if (cond >= aent->numconds) {
 
668
 
 
669
              /* we have a match so add prefix */
 
670
              tlen = 0;
 
671
              if (aent->appndl) {
 
672
                  strcpy(tword,aent->appnd);
 
673
                  tlen += aent->appndl;
 
674
               } 
 
675
               pp = tword + tlen;
 
676
               strcpy(pp, (word + aent->stripl));
 
677
               tlen = tlen + len - aent->stripl;
 
678
 
 
679
               if (numwords < MAX_WORDS) {
 
680
                  wlist[numwords].word = mystrdup(tword);
 
681
                  wlist[numwords].pallow = 0;
 
682
                  numwords++;
 
683
               }
 
684
            }
 
685
        }
 
686
    }
 
687
}
 
688
 
 
689
 
 
690
/* add a suffix to a word */
 
691
void suf_add (const char * word, int len, struct affent * ep, int num)
 
692
{
 
693
    struct affent *     aent;   
 
694
    int                 tlen;   
 
695
    int                 cond;   
 
696
    unsigned char *     cp;
 
697
    int                 i;
 
698
    char                tword[MAX_WD_LEN];
 
699
    char *              pp;
 
700
 
 
701
    for (aent = ep, i = num; i > 0; aent++, i--) {
 
702
 
 
703
      /* if conditions hold on root word 
 
704
       * then strip off strip string and add suffix
 
705
       */
 
706
 
 
707
      if ((len > aent->stripl) && (len >= aent->numconds)) {
 
708
        cp = (unsigned char *) (word + len);
 
709
        for (cond = aent->numconds;  --cond >= 0;  ) {
 
710
            if ((aent->conds[*--cp] & (1 << cond)) == 0) break;
 
711
        }
 
712
        if (cond < 0) {
 
713
          /* we have a matching condition */
 
714
          strcpy(tword,word);
 
715
          tlen = len;
 
716
          if (aent->stripl) {
 
717
             tlen -= aent->stripl;
 
718
          }
 
719
          pp = (tword + tlen);
 
720
          if (aent->appndl) {
 
721
               strcpy (pp, aent->appnd);
 
722
               tlen += aent->stripl;
 
723
          } else *pp = '\0';
 
724
 
 
725
          if (numwords < MAX_WORDS) {
 
726
              wlist[numwords].word = mystrdup(tword);
 
727
              wlist[numwords].pallow = (aent->xpflg & XPRODUCT);
 
728
              numwords++;
 
729
          }
 
730
        }
 
731
      }
 
732
    }
 
733
}
 
734
 
 
735
 
 
736
 
 
737
int expand_rootword(const char * ts, int wl, const char * ap, int al)
 
738
{
 
739
    int i;
 
740
    int j;
 
741
    int nh=0;
 
742
    int nwl;
 
743
 
 
744
    for (i=0; i < numsfx; i++) {
 
745
      if (strchr(ap,(stable[i].aep)->achar)) {
 
746
         suf_add(ts, wl, stable[i].aep, stable[i].num);
 
747
      }
 
748
    }
 
749
   
 
750
    nh = numwords;
 
751
 
 
752
    if (nh > 1) {
 
753
       for (j=1;j<nh;j++){
 
754
         if (wlist[j].pallow) {
 
755
            for (i=0; i < numpfx; i++) {
 
756
               if (strchr(ap,(ptable[i].aep)->achar)) {
 
757
                 if ((ptable[i].aep)->xpflg & XPRODUCT) {
 
758
                   nwl = strlen(wlist[j].word);
 
759
                   pfx_add(wlist[j].word, nwl, ptable[i].aep, ptable[i].num);
 
760
                 }
 
761
               }
 
762
            }
 
763
         }
 
764
       }
 
765
    }
 
766
 
 
767
    for (i=0; i < numpfx; i++) {
 
768
       if (strchr(ap,(ptable[i].aep)->achar)) {
 
769
          pfx_add(ts, wl, ptable[i].aep, ptable[i].num);
 
770
       }
 
771
    }
 
772
    return 0;
 
773
}
 
774
 
 
775
 
 
776
 
 
777
/* strip strings into token based on single char delimiter
 
778
 * acts like strsep() but only uses a delim char and not
 
779
 * a delim string
 
780
 */
 
781
char * mystrsep(char ** stringp, const char delim)
 
782
{
 
783
  char * rv = NULL;
 
784
  char * mp = *stringp;
 
785
  int n = strlen(mp);
 
786
  if (n > 0) {
 
787
    char * dp = (char *)memchr(mp,(int)((unsigned char)delim),n);
 
788
    if (dp) {
 
789
      int nc;
 
790
      *stringp = dp+1;
 
791
      nc = (int)((unsigned long)dp - (unsigned long)mp);
 
792
      rv = (char *) malloc(nc+1);
 
793
      memcpy(rv,mp,nc);
 
794
      *(rv+nc) = '\0';
 
795
      return rv;
 
796
    } else {
 
797
      rv = (char *) malloc(n+1);
 
798
      memcpy(rv, mp, n);
 
799
      *(rv+n) = '\0';
 
800
      *stringp = mp + n;
 
801
      return rv;
 
802
    }
 
803
  }
 
804
  return NULL;
 
805
}
 
806
 
 
807
 
 
808
char * mystrdup(const char * s)
 
809
{
 
810
  char * d = NULL;
 
811
  if (s) {
 
812
    int sl = strlen(s);
 
813
    d = (char *) malloc(((sl+1) * sizeof(char)));
 
814
    if (d) memcpy(d,s,((sl+1)*sizeof(char)));
 
815
  }
 
816
  return d;
 
817
}
 
818
 
 
819
 
 
820
void mychomp(char * s)
 
821
{
 
822
  int k = strlen(s);
 
823
  if (k > 0) *(s+k-1) = '\0';
 
824
  if ((k > 1) && (*(s+k-2) == '\r')) *(s+k-2) = '\0';
 
825
}
 
826