home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / TEXT / UTILITY / SSPELL11.ZIP / ROOT.C < prev    next >
Encoding:
C/C++ Source or Header  |  1992-01-26  |  12.6 KB  |  457 lines

  1. /* **************************************************************** */
  2. /*             sspell - similar to Unix spell                       */
  3. /*                        version 1.1                               */
  4. /*                                                                  */
  5. /* Author: Maurice Castro                                           */
  6. /* Release Date: 26 Jan 1992                                        */
  7. /* Bug Reports: maurice@bruce.cs.monash.edu.au                      */
  8. /*                                                                  */
  9. /* This code has been placed by the Author into the Public Domain.  */
  10. /* The code is NOT covered by any warranty, the user of the code is */
  11. /* solely responsible for determining the fitness of the program    */
  12. /* for their purpose. No liability is accepted by the author for    */
  13. /* the direct or indirect losses incurred through the use of this   */
  14. /* program.                                                         */
  15. /*                                                                  */
  16. /* Segments of this code may be used for any purpose that the user  */
  17. /* deems appropriate. It would be polite to acknowledge the source  */
  18. /* of the code. If you modify the code and redistribute it please   */
  19. /* include a message indicating your changes and how users may      */
  20. /* contact you for support.                                         */
  21. /*                                                                  */
  22. /* The author reserves the right to issue the official version of   */
  23. /* this program. If you have useful suggestions or changes for the  */
  24. /* code, please forward them to the author so that they might be    */
  25. /* incorporated into the official version                           */
  26. /*                                                                  */
  27. /* Please forward bug reports to the author via Internet.           */
  28. /*                                                                  */
  29. /* **************************************************************** */
  30.  
  31. /* determine the root of a word using the rules in the rule file */
  32.  
  33. #include <stdio.h>
  34. #include "strfn.h"
  35. #include "root.h"
  36. #include "error.h"
  37. #include "utility.h"
  38. #include "string.h"
  39.  
  40. #define MAXSTR 128
  41. #define PRE 0
  42. #define POST 1
  43.  
  44. typedef struct rule
  45. {
  46.     char *presuf;             /* prefix / suffix */
  47.     char *required;           /* character string  required at end of word */
  48.     char *forbid;             /* character string forbidden at end of word */
  49.     char *del;                /* characters to be deleted from end of word */
  50.     struct rule *next;
  51.     } RULE;
  52.  
  53. RULE *prefixlist;
  54. RULE *suffixlist;
  55.  
  56. void badline(lno)
  57. int lno;
  58. {
  59.    fprintf(stderr, "Warning: line %d in the rule file is badly formed\n",
  60.            lno);
  61.    }
  62.  
  63. void memfail()
  64. {
  65.    errormesg("Error: Out of Memory! Terminating",-3);
  66.    }
  67.  
  68. /* read the rules file */
  69. /* this file is made up of lines of the form: 
  70. /*     pre|post <prefix/suffix> <required> <forbiden> <delete> */
  71. /* Any blank fields should contain a single "-" all fields separated by */
  72. /* white space. A "#" in the first character position indicates a comment */
  73.  
  74. void initroot(file)
  75. char *file;
  76. {
  77.     FILE *f;
  78.     char instr[MAXSTR];
  79.     char *token;
  80.     int lno;
  81.     char *presuf;             /* prefix / suffix */
  82.     char *required;           /* character string  required at end of word */
  83.     char *forbid;             /* character string forbidden at end of word */
  84.     char *del;                /* characters to be deleted from end of word */
  85.     int prepost;
  86.     RULE *newitem;
  87.     RULE *prefixlast;
  88.     RULE *suffixlast;
  89.  
  90.     prefixlist = NULL;
  91.     suffixlist = NULL;
  92.    
  93.     f = fopen(file,"rt");
  94.     lno = -1;
  95.     while (!feof(f))
  96.     {
  97.        if (fgets(instr,MAXSTR-1,f)==NULL)
  98.           break;
  99.        lno++;
  100.        if (instr[0] == '#') 
  101.           continue;                    /* handle comments */
  102.        token = strtok(instr," \t\n");
  103.        if (!strcmp(token, "pre")) 
  104.            prepost = PRE;
  105.        else if (!strcmp(token, "post")) 
  106.            prepost = POST;
  107.        else
  108.        {
  109.            badline(lno);
  110.            continue;
  111.            }
  112.  
  113.        /* deal with the rest of line */
  114.        token = strtok(NULL," \t\n");
  115.        if (token == NULL) 
  116.        {
  117.           badline(lno);
  118.           continue;
  119.           }
  120.        if (!strcmp(token,"-")) 
  121.            presuf = NULL;
  122.        else
  123.        {
  124.            presuf = (char *) malloc(strlen(token)+1); 
  125.            if (presuf == NULL) memfail();
  126.            strcpy(presuf,token);
  127.            }
  128.        token = strtok(NULL," \t\n");
  129.        if (token == NULL)
  130.        {
  131.           badline(lno);
  132.           continue;
  133.           }
  134.        if (!strcmp(token,"-")) 
  135.            required = NULL;
  136.        else
  137.        {
  138.            required = (char *) malloc(strlen(token)+1); 
  139.            if (required == NULL) memfail();
  140.            strcpy(required,token);
  141.            }
  142.        token = strtok(NULL," \t\n");
  143.        if (token == NULL) 
  144.        {
  145.           badline(lno);
  146.           continue;
  147.           }
  148.        if (!strcmp(token,"-")) 
  149.            forbid = NULL;
  150.        else
  151.        {
  152.            forbid = (char *) malloc(strlen(token)+1); 
  153.            if (forbid == NULL) memfail();
  154.            strcpy(forbid,token);
  155.            }
  156.        token = strtok(NULL," \t\n");
  157.        if (token == NULL) 
  158.        {
  159.           badline(lno);
  160.           continue;
  161.           }
  162.        if (!strcmp(token,"-")) 
  163.            del = NULL;
  164.        else
  165.        {
  166.            del = (char *) malloc(strlen(token)+1); 
  167.            if (del == NULL) memfail();
  168.            strcpy(del,token);
  169.            }
  170.        newitem = (RULE *) malloc(sizeof(RULE));
  171.        if (newitem == NULL) memfail();
  172.        (*newitem).presuf = presuf;
  173.        (*newitem).required = required;
  174.        (*newitem).forbid = forbid;
  175.        (*newitem).del = del;
  176.        (*newitem).next = NULL;
  177.        if (prepost == PRE)
  178.        {
  179.            if (prefixlist == NULL)
  180.            {
  181.               prefixlist = newitem;
  182.               prefixlast = newitem;
  183.               }
  184.            else
  185.            {
  186.               (*prefixlast).next = newitem;
  187.               prefixlast = newitem;
  188.               }
  189.            }
  190.        else
  191.        {
  192.            if (suffixlist == NULL)
  193.            {
  194.               suffixlist = newitem;
  195.               suffixlast = newitem;
  196.               }
  197.            else
  198.            {
  199.               (*suffixlast).next = newitem;
  200.               suffixlast = newitem;
  201.               }
  202.            }
  203.        }
  204.     fclose(f);
  205.     }
  206.  
  207. int compend(a, b)
  208. char *a;
  209. char *b;
  210. {
  211.    char *sstr;
  212.  
  213.    sstr = a+strlen(a)-strlen(b);
  214.    if (!stricmp(sstr,b))
  215.        return(1);
  216.    return(0);    
  217.    }
  218.  
  219. /* determine the root of a given word */
  220. int prefix(in, outlst)
  221. char *in;
  222. WORDLST **outlst;
  223. {
  224.    RULE *pt;
  225.    char *sstr;
  226.    int idx;
  227.    int outflg;
  228.    WORDLST *newitem;
  229.  
  230.    *outlst = NULL;
  231.    outflg = 0;
  232.  
  233.    pt = prefixlist;
  234.    while (pt != NULL)
  235.    {
  236.       if (!strnicmp(pt->presuf, in, strlen(pt->presuf)))
  237.       { 
  238.          outflg = 1;
  239.          in += (strlen(pt->presuf));
  240.          /* add it to the output list */
  241.          newitem = (WORDLST *) malloc (sizeof(WORDLST));
  242.          newitem->prefix = NULL;
  243.          newitem->suffix = NULL;
  244.          if (newitem == NULL) 
  245.          {
  246.             memfail();
  247.             } 
  248.          newitem->word = (char *) malloc(strlen(in)+1);
  249.          if (newitem->word == NULL) 
  250.          {
  251.             memfail();
  252.             } 
  253.          strcpy(newitem->word, in);
  254.          newitem->prefix = (char *) malloc(strlen(pt->presuf)+2);
  255.          if (newitem->prefix == NULL) 
  256.          {
  257.             memfail();
  258.             } 
  259.          strcpy(newitem->prefix, pt->presuf);
  260.          strcat(newitem->prefix, "+");
  261.          newitem->next = *outlst;
  262.          *outlst = newitem;
  263.          }
  264.       pt = pt->next;
  265.       }
  266.    if (outflg) return(1);
  267.    return(0);
  268.    }
  269.  
  270. int suffix(in, outlst)
  271. char *in;
  272. WORDLST **outlst;
  273. {
  274.    RULE *pt;
  275.    char *sstr;
  276.    int idx;
  277.    char buf[MAXSTR];
  278.    char out[MAXSTR];
  279.    int flag;
  280.    int outflg;
  281.    WORDLST *newitem;
  282.    char *hold;
  283.  
  284.    *outlst = NULL;
  285.    outflg = 0;
  286.  
  287.    pt = suffixlist;
  288.    while (pt != NULL)
  289.    {
  290.       idx = strlen(in)-strlen(pt->presuf);
  291.       if (idx < 0)
  292.       {
  293.           pt = pt->next;
  294.           continue;        /* if it is negative there is no point */
  295.           }
  296.       sstr = in+idx;
  297.       if (stricmp(sstr,pt->presuf)) 
  298.       {
  299.          pt = pt->next;
  300.          continue; /* no match with ending so forget it */
  301.          }
  302.       strcpy(out,in);                 /* let us work on it */
  303.       *(out+idx) = NULL; /* delete the matching ending */
  304.       if (pt->del != NULL)            /* needed because of suns */
  305.          strcat(out,pt->del);            /* add on any deleted bits */
  306.       if (pt->required != NULL)
  307.       {
  308.           strcpy(buf,pt->required);
  309.           flag = 0;
  310.           sstr = strltok(buf," ,",&hold);
  311.           while (sstr != NULL)
  312.           {
  313.              if (compend(out,sstr)) flag = 1;
  314.              sstr = strltok(NULL, " ,",&hold);
  315.              } 
  316.           }
  317.       else
  318.           flag = 1;  /* nothing required so better say OK unless forbidden */
  319.       if (pt->forbid != NULL)
  320.       {
  321.           strcpy(buf,pt->forbid);
  322.           sstr = strltok(buf," ,",&hold);
  323.           while (sstr != NULL)
  324.           {
  325.              if (compend(out,sstr)) flag = 0;
  326.              sstr = strltok(NULL, " ,",&hold);
  327.              } 
  328.           }
  329.       if (flag) 
  330.       {
  331.          outflg = 1; /* it matched! */
  332.          /* add it to the output list */
  333.          newitem = (WORDLST *) malloc (sizeof(WORDLST));
  334.          newitem->prefix = NULL;
  335.          newitem->suffix = NULL;
  336.          if (newitem == NULL) 
  337.          {
  338.             memfail();
  339.             } 
  340.          newitem->word = (char *) malloc(strlen(out)+1);
  341.          if (newitem->word == NULL) 
  342.          {
  343.             memfail();
  344.             } 
  345.          strcpy(newitem->word, out);
  346.          if (pt->del ==NULL)
  347.          {
  348.             newitem->suffix = (char *) malloc(strlen(pt->presuf)+2);
  349.             if (newitem->suffix == NULL) 
  350.             {
  351.                memfail();
  352.                } 
  353.             strcpy(newitem->suffix, "+");
  354.             strcat(newitem->suffix, pt->presuf);
  355.             }
  356.          else
  357.          {
  358.             newitem->suffix = (char *) malloc(strlen(pt->presuf)+3+strlen(pt->del));
  359.             if (newitem->suffix == NULL) 
  360.             {
  361.                memfail();
  362.                } 
  363.             strcpy(newitem->suffix, "-");
  364.             strcat(newitem->suffix, pt->del);
  365.             strcat(newitem->suffix, "+");
  366.             strcat(newitem->suffix, pt->presuf);
  367.             }
  368.          newitem->next = *outlst;
  369.          *outlst = newitem;
  370.          }
  371.       pt = pt->next;
  372.       }
  373.    if (outflg) return(1);
  374.    return(0);
  375.    }
  376.  
  377. void root(in, outlst)
  378. char *in;
  379. WORDLST **outlst;
  380. {
  381.    WORDLST *prelst;
  382.    WORDLST *suflst;
  383.    WORDLST *end;
  384.    char prefbuf[MAXSTR];
  385.  
  386.    *outlst = NULL;
  387.    end = NULL;
  388.    /* check if there is a set of prefixes that fits */
  389.    if (prefix(in, &prelst))
  390.    {
  391.       /* add it to the output list */
  392.       *outlst = prelst;
  393.       end = *outlst;
  394.       while (end->next != NULL)
  395.       {
  396.           end = end->next;           /* trace to end of list */
  397.           }
  398.       while (prelst != NULL)
  399.       {
  400.          strcpy(prefbuf, prelst->prefix);
  401.          if (suffix(prelst->word, &suflst))
  402.          {
  403.             end->next = suflst; 
  404.             while (end->next != NULL)
  405.             {
  406.                 if ((end->prefix = (char *) malloc(strlen(prefbuf)+1)) == NULL)
  407.                 {
  408.                    memfail();
  409.                    }
  410.                 else
  411.                 {
  412.                    strcpy(end->prefix, prefbuf);
  413.                    }
  414.                 end = end->next;           /* trace to end of list */
  415.                 }
  416.             }
  417.          prelst = prelst->next;
  418.          }
  419.       }
  420.    if (suffix(in, &suflst))
  421.    {
  422.       if (*outlst != NULL)
  423.          end->next = suflst; 
  424.       else
  425.          *outlst = suflst;
  426.       }
  427.    }
  428.  
  429. void destroy(a)
  430. WORDLST *a;
  431. {
  432.    WORDLST *b;
  433.    while (a != NULL)
  434.    {
  435.        if (a->word != NULL) free(a->word);
  436.        if (a->prefix != NULL) free(a->prefix);
  437.        if (a->suffix != NULL) free(a->suffix);
  438.        b = a;
  439.        a = a->next;
  440.        free(b);
  441.        }
  442.    }
  443.  
  444. /* debugging code */
  445.  
  446. void prtrules(a)
  447. RULE *a;
  448. {
  449.    while (a!=NULL)
  450.    {
  451.        printf("item: %s required: %s forbidden: %s delete %s\n",
  452.                a->presuf, a->required, a->forbid, a->del);
  453.        a = a->next;
  454.        }
  455.    }
  456.  
  457.