home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V7 / usr / src / cmd / spell / spell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1979-01-19  |  8.0 KB  |  537 lines

  1. #include "spell.h"
  2. #define DLEV 2
  3.  
  4. char    *strcat();
  5. int    strip();
  6. char    *skipv();
  7. int    an();
  8. int    s();
  9. int    es();
  10. int    ily();
  11. int    ncy();
  12. int    CCe();
  13. int    VCe();
  14. int    bility();
  15. int    tion();
  16. int    ize();
  17. int    y_to_e();
  18. int    i_to_y();
  19. int    nop();
  20. int    metry();
  21.  
  22. struct suftab {
  23.     char *suf;
  24.     int (*p1)();
  25.     int n1;
  26.     char *d1;
  27.     char *a1;
  28.     int (*p2)();
  29.     int n2;
  30.     char *d2;
  31.     char *a2;
  32. } suftab[] = {
  33.     {"ssen",ily,4,"-y+iness","+ness" },
  34.     {"ssel",ily,4,"-y+i+less","+less" },
  35.     {"se",s,1,"","+s",        es,2,"-y+ies","+es" },
  36.     {"s'",s,2,"","+'s"},
  37.     {"s",s,1,"","+s"},
  38.     {"ecn",ncy,1,"","-t+ce"},
  39.     {"ycn",ncy,1,"","-cy+t"},
  40.     {"ytilb",nop,0,"",""},
  41.     {"ytilib",bility,5,"-le+ility",""},
  42.     {"elbaif",i_to_y,4,"-y+iable",""},
  43.     {"elba",CCe,4,"-e+able","+able"},
  44.     {"yti",CCe,3,"-e+ity","+ity"},
  45.     {"ylb",y_to_e,1,"-e+y",""},
  46.     {"yl",ily,2,"-y+ily","+ly"},
  47.     {"laci",strip,2,"","+al"},
  48.     {"latnem",strip,2,"","+al"},
  49.     {"lanoi",strip,2,"","+al"},
  50.     {"tnem",strip,4,"","+ment"},
  51.     {"gni",CCe,3,"-e+ing","+ing"},
  52.     {"reta",nop,0,"",""},
  53.     {"re",strip,1,"","+r",        i_to_y,2,"-y+ier","+er"},
  54.     {"de",strip,1,"","+d",        i_to_y,2,"-y+ied","+ed"},
  55.     {"citsi",strip,2,"","+ic"},
  56.     {"cihparg",i_to_y,1,"-y+ic",""},
  57.     {"tse",strip,2,"","+st",    i_to_y,3,"-y+iest","+est"},
  58.     {"cirtem",i_to_y,1,"-y+ic",""},
  59.     {"yrtem",metry,0,"-ry+er",""},
  60.     {"cigol",i_to_y,1,"-y+ic",""},
  61.     {"tsigol",i_to_y,2,"-y+ist",""},
  62.     {"tsi",VCe,3,"-e+ist","+ist"},
  63.     {"msi",VCe,3,"-e+ism","+ist"},
  64.     {"noitacif",i_to_y,6,"-y+ication",""},
  65.     {"noitazi",ize,5,"-e+ation",""},
  66.     {"rota",tion,2,"-e+or",""},
  67.     {"noit",tion,3,"-e+ion","+ion"},
  68.     {"naino",an,3,"","+ian"},
  69.     {"na",an,1,"","+n"},
  70.     {"evit",tion,3,"-e+ive","+ive"},
  71.     {"ezi",CCe,3,"-e+ize","+ize"},
  72.     {"pihs",strip,4,"","+ship"},
  73.     {"dooh",ily,4,"-y+ihood","+hood"},
  74.     {"luf",ily,3,"-y+iful","+ful"},
  75.     {"ekil",strip,4,"","+like"},
  76.     0
  77. };
  78.  
  79. char *preftab[] = {
  80.     "anti",
  81.     "bio",
  82.     "dis",
  83.     "electro",
  84.     "en",
  85.     "fore",
  86.     "hyper",
  87.     "intra",
  88.     "inter",
  89.     "iso",
  90.     "kilo",
  91.     "magneto",
  92.     "meta",
  93.     "micro",
  94.     "milli",
  95.     "mis",
  96.     "mono",
  97.     "multi",
  98.     "non",
  99.     "out",
  100.     "over",
  101.     "photo",
  102.     "poly",
  103.     "pre",
  104.     "pseudo",
  105.     "re",
  106.     "semi",
  107.     "stereo",
  108.     "sub",
  109.     "super",
  110.     "thermo",
  111.     "ultra",
  112.     "under",    /*must precede un*/
  113.     "un",
  114.     0
  115. };
  116.  
  117. int vflag;
  118. int xflag;
  119. char word[100];
  120. char original[100];
  121. char *deriv[40];
  122. char affix[40];
  123.  
  124. main(argc,argv)
  125. char **argv;
  126. {
  127.     register char *ep, *cp;
  128.     register char *dp;
  129.     int fold;
  130.     int j;
  131.     FILE *file, *found;
  132.     if(!prime(argc,argv)) {
  133.         fprintf(stderr,
  134.             "spell: cannot initialize hash table\n");
  135.         exit(1);
  136.     }
  137.     found = fopen(argv[2],"w");
  138.     for(argc-=3,argv+=3; argc>0 && argv[0][0]=='-'; argc--,argv++)
  139.         switch(argv[0][1]) {
  140.         case 'b':
  141.             ise();
  142.             break;
  143.         case 'v':
  144.             vflag++;
  145.             break;
  146.         case 'x':
  147.             xflag++;
  148.             break;
  149.         }
  150.     for(;; fprintf(file,"%s%s\n",affix,original)) {
  151.         affix[0] = 0;
  152.         file = found;
  153.         for(ep=word;(*ep=j=getchar())!='\n';ep++)
  154.             if(j == EOF)
  155.                 exit(0);
  156.         for(cp=word,dp=original; cp<ep; )
  157.             *dp++ = *cp++;
  158.         *dp = 0;
  159.         fold = 0;
  160.         for(cp=word;cp<ep;cp++)
  161.             if(islower(*cp))
  162.                 goto lcase;
  163.         if(putsuf(ep,".",0))
  164.             continue;
  165.         ++fold;
  166.         for(cp=original+1,dp=word+1;dp<ep;dp++,cp++)
  167.             *dp = Tolower(*cp);
  168. lcase:
  169.         if(putsuf(ep,".",0)||suffix(ep,0))
  170.             continue;
  171.         if(isupper(word[0])) {
  172.             for(cp=original,dp=word; *dp = *cp++; dp++)
  173.                 if (fold) *dp = Tolower(*dp);
  174.             word[0] = Tolower(word[0]);
  175.             goto lcase;
  176.         }
  177.         file = stdout;
  178.     }
  179. }
  180.  
  181. suffix(ep,lev)
  182. char *ep;
  183. {
  184.     register struct suftab *t;
  185.     register char *cp, *sp;
  186.     lev += DLEV;
  187.     deriv[lev] = deriv[lev-1] = 0;
  188.     for(t= &suftab[0];sp=t->suf;t++) {
  189.         cp = ep;
  190.         while(*sp)
  191.             if(*--cp!=*sp++)
  192.                 goto next;
  193.         for(sp=cp; --sp>=word&&!vowel(*sp); ) ;
  194.         if(sp<word)
  195.             return(0);
  196.         if((*t->p1)(ep-t->n1,t->d1,t->a1,lev+1))
  197.             return(1);
  198.         if(t->p2!=0) {
  199.             deriv[lev] = deriv[lev+1] = 0;
  200.             return((*t->p2)(ep-t->n2,t->d2,t->a2,lev));
  201.         }
  202.         return(0);
  203. next:        ;
  204.     }
  205.     return(0);
  206. }
  207.  
  208. nop()
  209. {
  210.     return(0);
  211. }
  212.  
  213. strip(ep,d,a,lev)
  214. char *ep,*d,*a;
  215. {
  216.     return(putsuf(ep,a,lev)||suffix(ep,lev));
  217. }
  218.  
  219. s(ep,d,a,lev)
  220. char *ep,*d,*a;
  221. {
  222.     if(lev>DLEV+1)
  223.         return(0);
  224.     if(*ep=='s'&&ep[-1]=='s')
  225.         return(0);
  226.     return(strip(ep,d,a,lev));
  227. }
  228.  
  229. an(ep,d,a,lev)
  230. char *ep,*d,*a;
  231. {
  232.     if(!isupper(*word))    /*must be proper name*/
  233.         return(0);
  234.     return(putsuf(ep,a,lev));
  235. }
  236.  
  237. ize(ep,d,a,lev)
  238. char *ep,*d,*a;
  239. {
  240.     *ep++ = 'e';
  241.     return(strip(ep,"",d,lev));
  242. }
  243.  
  244. y_to_e(ep,d,a,lev)
  245. char *ep,*d,*a;
  246. {
  247.     *ep++ = 'e';
  248.     return(strip(ep,"",d,lev));
  249. }
  250.  
  251. ily(ep,d,a,lev)
  252. char *ep,*d,*a;
  253. {
  254.     if(ep[-1]=='i')
  255.         return(i_to_y(ep,d,a,lev));
  256.     else
  257.         return(strip(ep,d,a,lev));
  258. }
  259.  
  260. ncy(ep,d,a,lev)
  261. char *ep, *d, *a;
  262. {
  263.     if(skipv(skipv(ep-1))<word)
  264.         return(0);
  265.     ep[-1] = 't';
  266.     return(strip(ep,d,a,lev));
  267. }
  268.  
  269. bility(ep,d,a,lev)
  270. char *ep,*d,*a;
  271. {
  272.     *ep++ = 'l';
  273.     return(y_to_e(ep,d,a,lev));
  274. }
  275.  
  276. i_to_y(ep,d,a,lev)
  277. char *ep,*d,*a;
  278. {
  279.     if(ep[-1]=='i') {
  280.         ep[-1] = 'y';
  281.         a = d;
  282.     }
  283.     return(strip(ep,"",a,lev));
  284. }
  285.  
  286. es(ep,d,a,lev)
  287. char *ep,*d,*a;
  288. {
  289.     if(lev>DLEV)
  290.         return(0);
  291.     switch(ep[-1]) {
  292.     default:
  293.         return(0);
  294.     case 'i':
  295.         return(i_to_y(ep,d,a,lev));
  296.     case 's':
  297.     case 'h':
  298.     case 'z':
  299.     case 'x':
  300.         return(strip(ep,d,a,lev));
  301.     }
  302. }
  303.  
  304. metry(ep,d,a,lev)
  305. char *ep, *d,*a;
  306. {
  307.     ep[-2] = 'e';
  308.     ep[-1] = 'r';
  309.     return(strip(ep,d,a,lev));
  310. }
  311.  
  312. tion(ep,d,a,lev)
  313. char *ep,*d,*a;
  314. {
  315.     switch(ep[-2]) {
  316.     case 'c':
  317.     case 'r':
  318.         return(putsuf(ep,a,lev));
  319.     case 'a':
  320.         return(y_to_e(ep,d,a,lev));
  321.     }
  322.     return(0);
  323. }
  324.  
  325. /*    possible consonant-consonant-e ending*/
  326. CCe(ep,d,a,lev)
  327. char *ep,*d,*a;
  328. {
  329.     switch(ep[-1]) {
  330.     case 'l':
  331.         if(vowel(ep[-2]))
  332.             break;
  333.         switch(ep[-2]) {
  334.         case 'l':
  335.         case 'r':
  336.         case 'w':
  337.             break;
  338.         default:
  339.             return(y_to_e(ep,d,a,lev));
  340.         }
  341.         break;
  342.     case 's':
  343.         if(ep[-2]=='s')
  344.             break;
  345.     case 'c':
  346.     case 'g':
  347.         if(*ep=='a')
  348.             return(0);
  349.     case 'v':
  350.     case 'z':
  351.         if(vowel(ep[-2]))
  352.             break;
  353.     case 'u':
  354.         if(y_to_e(ep,d,a,lev))
  355.             return(1);
  356.         if(!(ep[-2]=='n'&&ep[-1]=='g'))
  357.             return(0);
  358.     }
  359.     return(VCe(ep,d,a,lev));
  360. }
  361.  
  362. /*    possible consonant-vowel-consonant-e ending*/
  363. VCe(ep,d,a,lev)
  364. char *ep,*d,*a;
  365. {
  366.     char c;
  367.     c = ep[-1];
  368.     if(c=='e')
  369.         return(0);
  370.     if(!vowel(c) && vowel(ep[-2])) {
  371.         c = *ep;
  372.         *ep++ = 'e';
  373.         if(putsuf(ep,d,lev)||suffix(ep,lev))
  374.             return(1);
  375.         ep--;
  376.         *ep = c;
  377.     }
  378.     return(strip(ep,d,a,lev));
  379. }
  380.  
  381. char *lookuppref(wp,ep)
  382. char **wp;
  383. char *ep;
  384. {
  385.     register char **sp;
  386.     register char *bp,*cp;
  387.     for(sp=preftab;*sp;sp++) {
  388.         bp = *wp;
  389.         for(cp= *sp;*cp;cp++,bp++)
  390.             if(Tolower(*bp)!=*cp)
  391.                 goto next;
  392.         for(cp=bp;cp<ep;cp++) 
  393.             if(vowel(*cp)) {
  394.                 *wp = bp;
  395.                 return(*sp);
  396.             }
  397. next:    ;
  398.     }
  399.     return(0);
  400. }
  401.  
  402. putsuf(ep,a,lev)
  403. char *ep,*a;
  404. {
  405.     register char *cp;
  406.     char *bp;
  407.     register char *pp;
  408.     int val = 0;
  409.     char space[20];
  410.     deriv[lev] = a;
  411.     if(putw(word,ep,lev))
  412.         return(1);
  413.     bp = word;
  414.     pp = space;
  415.     deriv[lev+1] = pp;
  416.     while(cp=lookuppref(&bp,ep)) {
  417.         *pp++ = '+';
  418.         while(*pp = *cp++)
  419.             pp++;
  420.         if(putw(bp,ep,lev+1)) {
  421.             val = 1;
  422.             break;
  423.         }
  424.     }
  425.     deriv[lev+1] = deriv[lev+2] = 0;
  426.     return(val);
  427. }
  428.  
  429. putw(bp,ep,lev)
  430. char *bp,*ep;
  431. {
  432.     register i, j;
  433.     char duple[3];
  434.     if(ep-bp<=1)
  435.         return(0);
  436.     if(vowel(*ep)) {
  437.         if(monosyl(bp,ep))
  438.             return(0);
  439.     }
  440.     i = dict(bp,ep);
  441.     if(i==0&&vowel(*ep)&&ep[-1]==ep[-2]&&monosyl(bp,ep-1)) {
  442.         ep--;
  443.         deriv[++lev] = duple;
  444.         duple[0] = '+';
  445.         duple[1] = *ep;
  446.         duple[2] = 0;
  447.         i = dict(bp,ep);
  448.     }
  449.     if(vflag==0||i==0)
  450.         return(i);
  451.     j = lev;
  452.     do {
  453.         if(deriv[j])
  454.             strcat(affix,deriv[j]);
  455.     } while(--j>0);
  456.     strcat(affix,"\t");
  457.     return(i);
  458. }
  459.  
  460.  
  461. monosyl(bp,ep)
  462. char *bp, *ep;
  463. {
  464.     if(ep<bp+2)
  465.         return(0);
  466.     if(vowel(*--ep)||!vowel(*--ep)
  467.         ||ep[1]=='x'||ep[1]=='w')
  468.         return(0);
  469.     while(--ep>=bp)
  470.         if(vowel(*ep))
  471.             return(0);
  472.     return(1);
  473. }
  474.  
  475. char *
  476. skipv(s)
  477. char *s;
  478. {
  479.     if(s>=word&&vowel(*s))
  480.         s--;
  481.     while(s>=word&&!vowel(*s))
  482.         s--;
  483.     return(s);
  484. }
  485.  
  486. vowel(c)
  487. {
  488.     switch(Tolower(c)) {
  489.     case 'a':
  490.     case 'e':
  491.     case 'i':
  492.     case 'o':
  493.     case 'u':
  494.     case 'y':
  495.         return(1);
  496.     }
  497.     return(0);
  498. }
  499.  
  500. /* crummy way to Britishise */
  501. ise()
  502. {
  503.     register struct suftab *p;
  504.     for(p = suftab;p->suf;p++) {
  505.         ztos(p->suf);
  506.         ztos(p->d1);
  507.         ztos(p->a1);
  508.     }
  509. }
  510. ztos(s)
  511. char *s;
  512. {
  513.     for(;*s;s++)
  514.         if(*s=='z')
  515.             *s = 's';
  516. }
  517.  
  518. dict(bp,ep)
  519. char *bp, *ep;
  520. {
  521.     register char *wp;
  522.     long h;
  523.     register long *lp;
  524.     register i;
  525.     if(xflag)
  526.         printf("=%.*s\n",ep-bp,bp);
  527.     for(i=0; i<NP; i++) {
  528.         for (wp = bp, h = 0, lp = pow2[i]; wp < ep; ++wp, ++lp)
  529.             h += *wp * *lp;
  530.         h += '\n' * *lp;
  531.         h %= p[i];
  532.         if(get(h)==0)
  533.             return(0);
  534.     }
  535.     return(1);
  536. }
  537.