home *** CD-ROM | disk | FTP | other *** search
/ MacGames Sampler / PHT MacGames Bundle.iso / MacSource Folder / Samples from the CD / Editors / emacs / Emacs-1.14b1-sources / sources / utility-src / ispell / suf.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-03-04  |  13.1 KB  |  865 lines  |  [TEXT/EMAC]

  1. /* Copyright (C) 1990, 1993 Free Software Foundation, Inc.
  2.  
  3.    This file is part of GNU ISPELL.
  4.  
  5.    This program is free software; you can redistribute it and/or modify
  6.    it under the terms of the GNU General Public License as published by
  7.    the Free Software Foundation; either version 2, or (at your option)
  8.    any later version.
  9.  
  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.
  14.  
  15.    You should have received a copy of the GNU General Public License
  16.    along with this program; if not, write to the Free Software
  17.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  18.  
  19. #include "stdio.h"
  20. #include <ctype.h>
  21. #include "ispell.h"
  22. #include "hash.h"
  23. #include "good.h"
  24. #include "build.h"
  25. #include "charset.h"
  26.  
  27. #ifdef FPROTO
  28. int d_ending (char *, int);
  29. int t_ending (char *, int);
  30. int r_ending (char *, int);
  31. int g_ending (char *, int);
  32. int h_ending (char *, int);
  33. int s_ending (char *, int);
  34. int n_ending (char *, int);
  35. int e_ending (char *, int);
  36. int y_ending (char *, int);
  37. #else
  38. int d_ending ();
  39. int t_ending ();
  40. int r_ending ();
  41. int g_ending ();
  42. int h_ending ();
  43. int s_ending ();
  44. int n_ending ();
  45. int e_ending ();
  46. int y_ending ();
  47. #endif
  48.  
  49. struct hash_table_entry null_hte;
  50.  
  51. static entering = 0;
  52.  
  53. int sufcheck (char *w, int len);
  54.  
  55. void
  56. reapone (n)
  57.   int n;
  58. {
  59.   int i;
  60.   entering = 1;
  61.   for (i = 0; i < n; i++)
  62.     {
  63.       if (lookup (words[i]) ||
  64.       sufcheck (words[i], strlen (words[i])))
  65.     {
  66.       words[i][0] = 0;
  67.     }
  68.     }
  69.   entering = 0;
  70. }
  71.  
  72. void
  73. reap (h)
  74.      hash_index h;
  75. {
  76.   struct hash_table_entry hte;
  77.   int i, n;
  78.   char *entry;
  79.  
  80.   hash_retrieve (h, &hte);
  81.   if (hte.next >= HASH_SPECIAL && hte.next != HASH_END)
  82.     return;
  83.   null_hte.next = hte.next;
  84.   hash_store (h, &null_hte);
  85.  
  86.   entry = htetostr (&hte, h);
  87.   n = expand (entry);
  88.  
  89.   reapone (n);
  90.  
  91.   for (i = 0; i < n; i++)
  92.     if (words[i][0])
  93.       break;
  94.  
  95.   if (i != n)
  96.     {
  97.       /* still some word that wasn't taken care of */
  98.       hash_store (h, &hte);
  99.     }
  100. }
  101.  
  102. void
  103. reapall ()
  104. {
  105.   hash_index h;
  106.   for (h = 1; h < hashsize; h++)
  107.     reap (h);
  108. }
  109.  
  110. hash_index
  111. lookup (w)
  112.      char *w;
  113. {
  114.   comp_char outbuf[MAX_WORD_LEN];
  115.   int len;
  116.   hash_index h;
  117.  
  118.   len = lexword (w, strlen (w), outbuf);
  119.  
  120.   if (len == 0)
  121.     return (0);
  122.  
  123.   h = hash_lookup (outbuf, len);
  124.   return (h);
  125. }
  126.  
  127. void
  128. add_flag (h, flag)
  129.   hash_index h;
  130.   unsigned short flag;
  131. {
  132.   store_flags (h, get_flags (h) | flag);
  133. }
  134.  
  135.  
  136. int
  137. sufcheck (w, len)
  138.   char *w;
  139.   int len;
  140. {
  141.   char w1[MAX_WORD_LEN];
  142.   char *p, *q;
  143.   int n;
  144.   int c;
  145.  
  146.   if (len < 4)
  147.     return (0);
  148.  
  149.   for (p = w, q = w1, n = len; n-- && *p; p++, q++)
  150.     {
  151.       c = charset[(unsigned int) *p].lowercase;
  152.       if (c)
  153.     *q = c;
  154.       else
  155.     *q = *p;
  156.     }
  157.   *q = 0;
  158.   switch (w1[len - 1])
  159.     {
  160.     case 'd':
  161.       return (d_ending (w1, len));
  162.     case 't':
  163.       return (t_ending (w1, len));
  164.     case 'r':
  165.       return (r_ending (w1, len));
  166.     case 'g':
  167.       return (g_ending (w1, len));
  168.     case 'h':
  169.       return (h_ending (w1, len));
  170.     case 's':
  171.       return (s_ending (w1, len));
  172.     case 'n':
  173.       return (n_ending (w1, len));
  174.     case 'e':
  175.       return (e_ending (w1, len));
  176.     case 'y':
  177.       return (y_ending (w1, len));
  178.     default:
  179.       return (0);
  180.     }
  181. }
  182.  
  183. /* FOR CREATING, FIXING */
  184. int
  185. g_ending (w, len)
  186.   char *w;
  187.   int len;
  188. {
  189.   char *p;
  190.   hash_index h;
  191.  
  192.   p = w + len - 3;        /* if the word ends in 'ing', then *p == 'i' */
  193.  
  194.   if (p[0] != 'i')
  195.     return (0);
  196.   if (p[1] != 'n')
  197.     return (0);
  198.   if (p[2] != 'g')
  199.     return (0);
  200.  
  201.   p[0] = 'e';            /* change I to E, like in CREATING */
  202.   p[1] = 0;
  203.   len -= 2;
  204.  
  205.   if (len < 2)
  206.     return (0);
  207.  
  208.   if ((h = lookup (w)))
  209.     {
  210.       if (entering)
  211.     add_flag (h, G_FLAG);
  212.       if (get_flags (h) & G_FLAG)
  213.     return (2);
  214.     }
  215.  
  216.   p[0] = 0;
  217.   len -= 1;
  218.  
  219.   if (len < 2)
  220.     return (0);
  221.  
  222.   if (p[-1] == 'e')
  223.     return (0);            /* this stops CREATEING */
  224.  
  225.   if ((h = lookup (w)))
  226.     {
  227.       if (entering)
  228.     add_flag (h, G_FLAG);
  229.       if (get_flags (h) & G_FLAG)
  230.     return (2);
  231.     }
  232.   return (0);
  233. }
  234.  
  235. /* FOR CREATED, IMPLIED, CROSSED */
  236. int
  237. d_ending (w, len)
  238.   char *w;
  239.   int len;
  240. {
  241.   char *p;
  242.   hash_index h;
  243.  
  244.   p = w + len - 2;
  245.  
  246.   if (p[0] != 'e')
  247.     return (0);
  248.   if (p[1] != 'd')
  249.     return (0);
  250.  
  251.   p[1] = 0;            /* kill 'd' */
  252.   len--;
  253.  
  254.   /* like CREATED */
  255.   if ((h = lookup (w)))
  256.     {
  257.       if (entering)
  258.     add_flag (h, D_FLAG);
  259.       if (get_flags (h) & D_FLAG)
  260.     return (2);
  261.     }
  262.  
  263.   if (len < 3)
  264.     return (0);
  265.  
  266.   p[0] = 0;
  267.   p--;
  268.  
  269.   /* ED is now completely gone */
  270.  
  271.   if (p[0] == 'i' && !isvowel (p[-1]))
  272.     {
  273.       p[0] = 'y';
  274.       if ((h = lookup (w)))
  275.     {
  276.       if (entering)
  277.         add_flag (h, D_FLAG);
  278.       if (get_flags (h) & D_FLAG)
  279.         return (2);
  280.     }
  281.  
  282.       p[0] = 'i';
  283.     }
  284.  
  285.   if ((p[0] != 'e' && p[0] != 'y') ||
  286.       (p[0] == 'y' && isvowel (p[-1])))
  287.     {
  288.       if ((h = lookup (w)))
  289.     {
  290.       if (entering)
  291.         add_flag (h, D_FLAG);
  292.       if (get_flags (h) & D_FLAG)
  293.         return (2);
  294.     }
  295.     }
  296.  
  297.   return (0);
  298. }
  299.  
  300. /* FOR LATEST, DIRTIEST, BOLDEST */
  301. int
  302. t_ending (w, len)
  303.   char *w;
  304.   int len;
  305. {
  306.   char *p;
  307.   hash_index h;
  308.  
  309.   p = w + len - 3;
  310.  
  311.   if (p[0] != 'e')
  312.     return (0);
  313.   if (p[1] != 's')
  314.     return (0);
  315.   if (p[2] != 't')
  316.     return (0);
  317.  
  318.   p[1] = 0;            /* kill 's' */
  319.   len -= 2;
  320.  
  321.   if ((h = lookup (w)))
  322.     {
  323.       if (entering)
  324.     add_flag (h, T_FLAG);
  325.       if (get_flags (h) & T_FLAG)
  326.     return (2);
  327.     }
  328.  
  329.   if (len < 3)
  330.     return (0);
  331.  
  332.   p[0] = 0;
  333.   p--;
  334.  
  335.   /* EST is now completely gone */
  336.  
  337.   if (p[0] == 'i' && !isvowel (p[-1]))
  338.     {
  339.       p[0] = 'y';
  340.       if ((h = lookup (w)))
  341.     {
  342.       if (entering)
  343.         add_flag (h, T_FLAG);
  344.       if (get_flags (h) & T_FLAG)
  345.         return (2);
  346.     }
  347.       return (0);
  348.     }
  349.  
  350.   if ((p[0] != 'e' && p[0] != 'y') ||
  351.       (p[0] == 'y' && isvowel (p[-1])))
  352.     {
  353.       if ((h = lookup (w)))
  354.     {
  355.       if (entering)
  356.         add_flag (h, T_FLAG);
  357.       if (get_flags (h) & T_FLAG)
  358.         return (2);
  359.     }
  360.     }
  361.   return (0);
  362. }
  363.  
  364. /* FOR LATER, DIRTIER, BOLDER */
  365. int
  366. r_ending (w, len)
  367.   char *w;
  368.   int len;
  369. {
  370.   char *p;
  371.   hash_index h;
  372.  
  373.   p = w + len - 2;
  374.  
  375.   if (p[0] != 'e')
  376.     return (0);
  377.   if (p[1] != 'r')
  378.     return (0);
  379.  
  380.   p[1] = 0;            /* kill 'r' */
  381.   len--;
  382.  
  383.   if ((h = lookup (w)))
  384.     {
  385.       if (entering)
  386.     add_flag (h, R_FLAG);
  387.       if (get_flags (h) & R_FLAG)
  388.     return (2);
  389.     }
  390.  
  391.   if (len < 3)
  392.     return (0);
  393.  
  394.   p[0] = 0;
  395.   p--;
  396.  
  397.   /* ER is now completely gone */
  398.  
  399.   if (p[0] == 'i' && !isvowel (p[-1]))
  400.     {
  401.       p[0] = 'y';
  402.       if ((h = lookup (w)))
  403.     {
  404.       if (entering)
  405.         add_flag (h, R_FLAG);
  406.       if (get_flags (h) & R_FLAG)
  407.         return (2);
  408.     }
  409.       return (0);
  410.     }
  411.  
  412.   if ((p[0] != 'e' && p[0] != 'y') ||
  413.       (p[0] == 'y' && isvowel (p[-1])))
  414.     {
  415.       if ((h = lookup (w)))
  416.     {
  417.       if (entering)
  418.         add_flag (h, R_FLAG);
  419.       if (get_flags (h) & R_FLAG)
  420.         return (2);
  421.     }
  422.     }
  423.   return (0);
  424. }
  425.  
  426. /* FOR HUNDREDTH, TWENTIETH */
  427. int
  428. h_ending (w, len)
  429.   char *w;
  430.   int len;
  431. {
  432.   char *p;
  433.   hash_index h;
  434.  
  435.   p = w + len - 2;
  436.  
  437.   if (p[0] != 't')
  438.     return (0);
  439.   if (p[1] != 'h')
  440.     return (0);
  441.  
  442.   *p = 0;
  443.   p -= 2;
  444.  
  445.   if (p[0] == 'i' && p[1] == 'e')
  446.     {
  447.       p[0] = 'y';
  448.       p[1] = 0;
  449.     }
  450.   else
  451.     {
  452.       if (p[1] == 'y')
  453.     return (0);        /* stops myth -> my/h */
  454.     }
  455.  
  456.   if ((h = lookup (w)))
  457.     {
  458.       if (entering)
  459.     add_flag (h, H_FLAG);
  460.       if (get_flags (h) & H_FLAG)
  461.     return (2);
  462.     }
  463.  
  464.   return (0);
  465. }
  466.  
  467. /*
  468.  * check for flags: X, J, Z, S, P, M
  469.  *
  470.  * X    -ions or -ications or -ens
  471.  * J    -ings
  472.  * Z    -ers or -iers
  473.  * S    -ies or -es or -s
  474.  * P    -iness or -ness
  475.  * M    -'s
  476.  */
  477.  
  478. /* FOR ALL SORTS OF THINGS ENDING IN S */
  479. int
  480. s_ending (w, len)
  481.   char *w;
  482.   int len;
  483. {
  484.   char *p;
  485.   hash_index h;
  486.  
  487.   p = w + len;
  488.  
  489.   /* len >= 4 if we get here at all */
  490.  
  491.   if (p[-2] == '\'')
  492.     {
  493.       p[-2] = 0;
  494.       if ((h = lookup (w)))
  495.     {
  496.       if (entering)
  497.         add_flag (h, M_FLAG);
  498.       if (get_flags (h) & M_FLAG)
  499.         return (2);
  500.     }
  501.       return (0);
  502.     }
  503.   if (!issxzhy (p[-2]))
  504.     {
  505.       /* see if it was simple adding S */
  506.       p[-1] = 0;        /* kill S */
  507.       if ((h = lookup (w)))
  508.     {
  509.       if (entering)
  510.         add_flag (h, S_FLAG);
  511.       if (get_flags (h) & S_FLAG)
  512.         return (2);
  513.     }
  514.     }
  515.  
  516.   if (p[-2] == 'y')
  517.     {
  518.       if (!isvowel (p[-3]))
  519.     return (0);
  520.       p[-1] = 0;
  521.       if ((h = lookup (w)))
  522.     {
  523.       if (entering)
  524.         add_flag (h, S_FLAG);
  525.       if (get_flags (h) & S_FLAG)
  526.         return (2);
  527.     }
  528.       return (0);
  529.     }
  530.  
  531.   if (p[-2] == 'e')
  532.     {
  533.       if (issxzh (p[-3]))
  534.     {
  535.       p[-2] = 0;
  536.  
  537.       if ((h = lookup (w)))
  538.         {
  539.           if (entering)
  540.         add_flag (h, S_FLAG);
  541.           if (get_flags (h) & S_FLAG)
  542.         return (2);
  543.         }
  544.  
  545.       return (0);
  546.     }
  547.  
  548.       if (p[-3] == 'i')
  549.     {
  550.       if (isvowel (p[-4]))
  551.         return (0);
  552.       p[-3] = 'y';
  553.       p[-2] = 0;
  554.       if ((h = lookup (w)))
  555.         {
  556.           if (entering)
  557.         add_flag (h, S_FLAG);
  558.           if (get_flags (h) & S_FLAG)
  559.         return (2);
  560.         }
  561.     }
  562.       return (0);
  563.     }
  564.  
  565.   if (p[-2] == 's')
  566.     {
  567.       if (p[-4] != 'n' || p[-3] != 'e')
  568.     return (0);
  569.       if (len < 5)
  570.     return (0);
  571.       p[-4] = 0;        /* zap NESS */
  572.       if (p[-5] == 'i' && !isvowel (p[-6]))
  573.     {
  574.       p[-5] = 'y';
  575.       if ((h = lookup (w)))
  576.         {
  577.           if (entering)
  578.         add_flag (h, P_FLAG);
  579.           if (get_flags (h) & P_FLAG)
  580.         return (2);
  581.           return (0);
  582.         }
  583.       p[-5] = 'i';
  584.     }
  585.  
  586.       if (p[-5] == 'y' && !isvowel (p[-6]))
  587.     return (0);        /* stops shyness -> shy/p */
  588.  
  589.       if ((h = lookup (w)))
  590.     {
  591.       if (entering)
  592.         add_flag (h, P_FLAG);
  593.       if (get_flags (h) & P_FLAG)
  594.         return (2);
  595.     }
  596.  
  597.       return (0);
  598.     }
  599.  
  600.   if (p[-2] == 'r')
  601.     {
  602.       if (p[-3] != 'e')
  603.     return (0);
  604.       p[-2] = 0;
  605.       if ((h = lookup (w)))
  606.     {
  607.       if (entering)
  608.         add_flag (h, Z_FLAG);
  609.       if (get_flags (h) & Z_FLAG)
  610.         return (2);
  611.     }
  612.  
  613.       if (p[-4] != 'e')
  614.     {
  615.       if (p[-4] == 'i' && !isvowel (p[-5]))
  616.         p[-4] = 'y';
  617.       p[-3] = 0;
  618.       if ((h = lookup (w)))
  619.         {
  620.           if (entering)
  621.         add_flag (h, Z_FLAG);
  622.           if (get_flags (h) & Z_FLAG)
  623.         return (2);
  624.         }
  625.     }
  626.       return (0);
  627.     }
  628.  
  629.   if (p[-2] == 'g')
  630.     {
  631.       if (p[-4] != 'i' || p[-3] != 'n')
  632.     return (0);
  633.       p[-4] = 'e';
  634.       p[-3] = 0;
  635.       if ((h = lookup (w)))
  636.     {
  637.       if (entering)
  638.         add_flag (h, J_FLAG);
  639.       if (get_flags (h) & J_FLAG)
  640.         return (2);
  641.       return (0);
  642.     }
  643.  
  644.       if (len < 5)
  645.     return (0);
  646.       if (p[-5] == 'e')
  647.     return (0);
  648.       p[-4] = 0;
  649.  
  650.       if ((h = lookup (w)))
  651.     {
  652.       if (entering)
  653.         add_flag (h, J_FLAG);
  654.       if (get_flags (h) & J_FLAG)
  655.         return (2);
  656.     }
  657.       return (0);
  658.     }
  659.  
  660.   if (p[-2] == 'n')
  661.     {
  662.       if (p[-3] == 'e' && p[-4] != 'e' && p[-4] != 'y')
  663.     {
  664.       p[-3] = 0;
  665.       if ((h = lookup (w)))
  666.         {
  667.           if (entering)
  668.         add_flag (h, X_FLAG);
  669.           if (get_flags (h) & X_FLAG)
  670.         return (2);
  671.         }
  672.       return (0);
  673.     }
  674.  
  675.       if (p[-4] != 'i' || p[-3] != 'o')
  676.     return (0);
  677.       p[-4] = 'e';
  678.       p[-3] = 0;
  679.       if ((h = lookup (w)))
  680.     {
  681.       if (entering)
  682.         add_flag (h, X_FLAG);
  683.       if (get_flags (h) & X_FLAG)
  684.         return (2);
  685.     }
  686.  
  687.       if (len < 8)
  688.     return (0);
  689.       if (p[-8] != 'i')
  690.     return (0);
  691.       if (p[-7] != 'c')
  692.     return (0);
  693.       if (p[-6] != 'a')
  694.     return (0);
  695.       if (p[-5] != 't')
  696.     return (0);
  697.  
  698.       p[-8] = 'y';
  699.       p[-7] = 0;
  700.       if ((h = lookup (w)))
  701.     {
  702.       if (entering)
  703.         add_flag (h, X_FLAG);
  704.       if (get_flags (h) & X_FLAG)
  705.         return (2);
  706.     }
  707.     }
  708.   return (0);
  709. }
  710.  
  711. /* TIGHTEN, CREATION, MULIPLICATION */
  712. /* only the N flag */
  713. int
  714. n_ending (w, len)
  715.   char *w;
  716.   int len;
  717. {
  718.   char *p;
  719.   hash_index h;
  720.  
  721.   p = w + len;
  722.  
  723.   if (p[-2] == 'e')
  724.     {
  725.       if (p[-3] == 'e' || p[-3] == 'y')
  726.     return (0);
  727.       p[-2] = 0;
  728.       len -= 2;
  729.       if ((h = lookup (w)))
  730.     {
  731.       if (entering)
  732.         add_flag (h, N_FLAG);
  733.       if (get_flags (h) & N_FLAG)
  734.         return (2);
  735.     }
  736.       return (0);
  737.     }
  738.  
  739.   if (p[-3] != 'i')
  740.     return (0);
  741.   if (p[-2] != 'o')
  742.     return (0);
  743.   if (p[-1] != 'n')
  744.     return (0);
  745.  
  746.   p[-3] = 'e';
  747.   p[-2] = 0;
  748.   len -= 2;
  749.  
  750.   if ((h = lookup (w)))
  751.     {
  752.       if (entering)
  753.     add_flag (h, N_FLAG);
  754.       if (get_flags (h) & N_FLAG)
  755.     return (2);
  756.  
  757.       return (0);
  758.     }
  759.  
  760.   /* really against ICATION */
  761.   if (p[-7] != 'i')
  762.     return (0);
  763.   if (p[-6] != 'c')
  764.     return (0);
  765.   if (p[-5] != 'a')
  766.     return (0);
  767.   if (p[-4] != 't')
  768.     return (0);
  769.   if (p[-3] != 'e')
  770.     return (0);
  771.  
  772.   p[-7] = 'y';
  773.   p[-6] = 0;
  774.   len -= 4;
  775.  
  776.   if ((h = lookup (w)))
  777.     {
  778.       if (entering)
  779.     add_flag (h, N_FLAG);
  780.       if (get_flags (h) & N_FLAG)
  781.     return (2);
  782.     }
  783.  
  784.   return (0);
  785. }
  786.  
  787. /* FOR CREATIVE, PREVENTIVE */
  788. /* flags: v */
  789. int
  790. e_ending (w, len)
  791.   char *w;
  792.   int len;
  793. {
  794.   char *p;
  795.   hash_index h;
  796.  
  797.   p = w + len;
  798.  
  799.   if (p[-3] != 'i')
  800.     return (0);
  801.   if (p[-2] != 'v')
  802.     return (0);
  803.   if (p[-1] != 'e')
  804.     return (0);
  805.  
  806.   p[-3] = 'e';
  807.   p[-2] = 0;
  808.   len -= 2;
  809.  
  810.   if ((h = lookup (w)))
  811.     {
  812.       if (entering)
  813.     add_flag (h, V_FLAG);
  814.       if (get_flags (h) & V_FLAG)
  815.     return (2);
  816.       return (0);
  817.     }
  818.  
  819.   if (p[-4] == 'e')
  820.     return (0);
  821.  
  822.   p[-3] = 0;
  823.  
  824.   if ((h = lookup (w)))
  825.     {
  826.       if (entering)
  827.     add_flag (h, V_FLAG);
  828.       if (get_flags (h) & V_FLAG)
  829.     return (2);
  830.     }
  831.  
  832.   return (0);
  833. }
  834.  
  835. /* FOR QUICKLY */
  836. /* flags: y */
  837. int
  838. y_ending (w, len)
  839.   char *w;
  840.   int len;
  841. {
  842.   char *p;
  843.   hash_index h;
  844.  
  845.   p = w + len;
  846.  
  847.   if (p[-2] != 'l')
  848.     return (0);
  849.   if (p[-1] != 'y')
  850.     return (0);
  851.  
  852.   p[-2] = 0;
  853.   len -= 2;
  854.  
  855.   if ((h = lookup (w)))
  856.     {
  857.       if (entering)
  858.     add_flag (h, Y_FLAG);
  859.       if (get_flags (h) & Y_FLAG)
  860.     return (2);
  861.     }
  862.  
  863.   return (0);
  864. }
  865.