home *** CD-ROM | disk | FTP | other *** search
/ Amiga Elysian Archive / AmigaElysianArchive.iso / wp_dtp / ispell.lha / icombine.c < prev    next >
C/C++ Source or Header  |  1990-12-28  |  6KB  |  229 lines

  1. /*
  2.    icombine:  combine multiple ispell dictionary entries into a single
  3.               entry with the options of all entries
  4.  
  5.    Author:  Gary Puckering
  6.             Cognos, Inc.
  7.  
  8.    Written:  January 29, 1987
  9.  
  10.    Notes:  Input lines consist of a word followed optionally by
  11.            by one or more flags.  e.g CREATE/V/N/S
  12.  
  13.            Flags on lines with identical root words are combined.
  14.            No editing on flags is performed.
  15.            Flags are forced to uppercase, but roots are left alone.
  16.            Old-style flags, like /X/N will be output as /NX.
  17.            Flags are output in alphabetical order.
  18.            Non-letters appearing before the first "/" are retained,
  19.              those after are dropped.
  20.            Root words that differ only in capitalization are combined.
  21. */
  22.  
  23. #include <stdio.h>
  24. #include <ctype.h>
  25. #include <string.h>
  26. #include <proto/all.h>
  27. #include "config.h"
  28. #include "ispell.h"
  29.  
  30. void putword (void);
  31. void parse (char ln[], char wrd[], char flgs[]);
  32. void getflags (char *flgs);
  33. void putflags (void);
  34. int resolvecaps (char *word, char *ucword, char *lastword, char *uclastword);
  35. void uccopy (char *dest, char *src);
  36.  
  37. #define MAXFLAGS 26        /* letters A-Z */
  38. #define MAXLINE 255        /* maximum line size */
  39.  
  40. #define TRUE 1
  41. #define FALSE 0
  42. typedef int bool;
  43.  
  44. bool flagtbl[MAXFLAGS];        /* array of flag options */
  45.  
  46. char line[MAXLINE];        /* current line */
  47. char lastword[MAXLINE];        /* previous word */
  48. char uclastword[MAXLINE];    /* uppercase version of lastword */
  49. char word[MAXLINE];        /* current word */
  50. char ucword[MAXLINE];        /* uppercase version of current word */
  51. char flags[MAXLINE];        /* current flags */
  52. int expand = 0;            /* if NZ, expand instead of combining */
  53.  
  54. void main (int argc, char *argv[])
  55. {
  56.  
  57.   if (argc > 1 && strcmp (argv[1], "-e") == 0)
  58.     expand = 1;
  59.   if (gets (line))
  60.     {
  61.       parse (line, lastword, flags);
  62.       uccopy (uclastword, lastword);
  63.       getflags (flags);
  64.     }
  65.   else
  66.     return;
  67.  
  68.   while (gets (line))
  69.     {
  70.       parse (line, word, flags);
  71.       uccopy (ucword, word);
  72.       if (strcmp (word, lastword) != 0)    /* possibly different word */
  73.     {
  74.       if (strcmp (ucword, uclastword) != 0    /* truly different word */
  75.           || resolvecaps (word, ucword, lastword, uclastword))
  76.         {            /* or caps differ */
  77.           putword ();
  78.           strcpy (lastword, word);
  79.           strcpy (uclastword, ucword);
  80.         }
  81.     }
  82.       getflags (flags);
  83.     }
  84.   putword ();
  85.   return;
  86. }
  87.  
  88. void putword (void)
  89. {
  90.   printf ("%s", lastword);
  91.   putflags ();
  92. }
  93.  
  94. void parse (char ln[], char wrd[], char flgs[])
  95. {
  96.   register char *p, *q;
  97.  
  98.   /* copy line up to first "/" or to end */
  99.   for (p = ln, q = wrd; *p && *p != '/'; p++, q++)
  100.     *q = *p;
  101.   *q = NULL;
  102.  
  103.   strcpy (flgs, p);        /* copy from "/" to end */
  104. }
  105.  
  106. void getflags (char *flgs)
  107. {
  108.   register char *p;
  109.  
  110.   for (p = flgs; *p; p++)
  111.     if (*p != '/')
  112.       {
  113.     if (islower (*p))
  114.       *p = toupper (*p);
  115.     if (isupper (*p))
  116.       flagtbl[(*p) - 'A'] = TRUE;
  117.       }
  118. }
  119.  
  120. void putflags (void)
  121. {
  122.   register int i;
  123.   int slashout = 0;
  124.  
  125.   if (expand)
  126.     putchar ('\n');
  127.  
  128.   for (i = 0; i < MAXFLAGS; i++)
  129.     if (flagtbl[i])
  130.       {
  131.     if (expand)
  132.       printf ("%s/%c\n", lastword, i + 'A');
  133.     else
  134.       {
  135.         if (!slashout)
  136.           putchar ('/');
  137.         slashout = 1;
  138.         putchar (i + 'A');
  139.       }
  140.     flagtbl[i] = FALSE;
  141.       }
  142.   if (!expand)
  143.     putchar ('\n');
  144. }
  145.  
  146. /*
  147.  * This routine resolves capitalization conflicts.  The idea is to combine
  148.  * only those cases that ispell can "uncombine".
  149.  *
  150.  * Entry: word and lastword differ, but only by case.
  151.  *
  152.  * Exit: Returns 1 if word and lastword both need to be in the dictionary,
  153.  *     0 if they can be handled by a single entry.  If the return is zero,
  154.  *     lastword may have been modified to reflect the union of the two
  155.  *     entries.
  156.  *
  157.  * Rules:
  158.  *
  159.  * (1) If either word is entirely in upper case, it "loses" to the other
  160.  *     word.  The "winning" word is copied to lastword, and 0 is returned.
  161.  * (2) If either word is "followcase" (defined as being mixed case with a
  162.  *     capital letter appearing after the first character), the two
  163.  *     variants are considered to differ, and 1 is returned.  Furthermore,
  164.  *     a flag is set (by copying the word to "lastfollow") so that all
  165.  *     future variants fo the word will be considered to differ.
  166.  * (3) If one word is capitalized and the other is all-lowercase, the
  167.  *     lowercase word "wins".  It is copied to lastword, and 0 is returned.
  168.  *     HOWEVER, if a "followcase" variant of the word has been seen, this
  169.  *     rule does not apply, and rule (4) will cause the words to be
  170.  *     considered different.
  171.  * (4) If a "followcase" variant of the word has been seen, the words are
  172.  *     always considered to differ.  1 is returned.
  173.  *
  174.  * Note that the input must be sorted with "sort -t/ +0f -1 +0 -1" for this
  175.  * code to work.
  176.  */
  177. int resolvecaps (char *word, char *ucword, char *lastword, char *uclastword)
  178. {
  179.   register char *w;
  180.   register char *lw;
  181.   static char lastfollow[200] = "";
  182.  
  183.   /* Rule (1): Upper case loses */
  184.   for (w = word; *w && !mylower (*w); w++)
  185.     ;
  186.   if (*w == '\0')
  187.     return 0;
  188.   for (lw = lastword; *lw && !mylower (*lw); lw++)
  189.     ;
  190.   if (*lw == '\0')
  191.     {
  192.       strcpy (lastword, word);
  193.       strcpy (uclastword, ucword);
  194.       return 0;
  195.     }
  196.   /* Rule (4):  followcase forces all subsequent variants to be different. */
  197.   if (strcmp (ucword, lastfollow) == 0)
  198.     return 1;
  199.   /* Rule (2):  "followcase" is different. */
  200.   for (w = word + 1, lw = lastword + 1;
  201.        *w && !myupper (*w) && !myupper (*lw);
  202.        w++, lw++)
  203.     ;
  204.   if (*w)            /* We don't test *lw 'cause lengths are the same */
  205.     {
  206.       strcpy (lastfollow, ucword);
  207.       return 1;
  208.     }
  209.   /* Rule (3):  all-lowercase beats capitalized */
  210.   if (myupper (lastword[0]))
  211.     {
  212.       strcpy (lastword, word);
  213.       strcpy (uclastword, ucword);
  214.     }
  215.   return 0;
  216. }
  217.  
  218. void uccopy (char *dest, char *src)
  219. {
  220.   while (*src)
  221.     {
  222.       if (mylower (*src))
  223.     *dest++ = toupper (*src++);
  224.       else
  225.     *dest++ = *src++;
  226.     }
  227.   *dest = '\0';
  228. }
  229.