home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / OS2 / ISPELL40.ZIP / SRC.ZIP / PRIV.C < prev    next >
C/C++ Source or Header  |  1994-01-30  |  8KB  |  453 lines

  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.  
  22. #ifdef HAVE_MALLOC_H
  23. #include <malloc.h>
  24. #endif
  25.  
  26. #include "ispell.h"
  27. #include "hash.h"
  28.  
  29. static int p_nextsize = 53;    /* first hash size, should be prime */
  30. static char **p_hash, **p_end;
  31. static int p_size, p_used, p_thresh;
  32. static int p_modified;
  33.  
  34. int
  35. p_lookup (word, alllower)
  36.   char *word;
  37.   int alllower;
  38. {
  39.   int code;
  40.   char **pe;
  41.   char local[MAX_WORD_LEN], *p, *q;
  42.  
  43.   if (p_size == 0)
  44.     return (0);
  45.  
  46.   if (alllower)
  47.     {
  48.       p = word;            /* already lower case */
  49.     }
  50.   else
  51.     {
  52.       downcase (local, word);
  53.       p = local;
  54.     }
  55.  
  56.   code = hash (p) % p_size;
  57.   pe = p_hash + code;
  58.   while ((q = *pe))
  59.     {
  60.       if (*q == '!')
  61.     q++;
  62.       if (strcmp (q, p) == 0)
  63.     return (1);
  64.       pe++;
  65.       if (pe == p_end)
  66.     pe = p_hash;
  67.     }
  68.   return (0);
  69. }
  70.  
  71. int
  72. p_delete (word)
  73.   char *word;
  74. {
  75.   int code;
  76.   char **pe;
  77.   char local[MAX_WORD_LEN], *p, *q;
  78.  
  79.   if (p_size == 0)
  80.     return (-1);
  81.  
  82.   downcase (local, word);
  83.   p = local;
  84.  
  85.   code = hash (p) % p_size;
  86.   pe = p_hash + code;
  87.   while ((q = *pe))
  88.     {
  89.       if (*q == '!')
  90.     q++;
  91.       if (strcmp (q, p) == 0)
  92.     {
  93.       (*pe)[0] = '#';
  94.       (*pe)[1] = 0;
  95.       p_modified = 1;
  96.       return (0);
  97.     }
  98.       pe++;
  99.       if (pe == p_end)
  100.     pe = p_hash;
  101.     }
  102.   return (-1);
  103. }
  104.  
  105. int
  106. p_enter (word, copy, keep)
  107.   char *word;
  108.   int copy, keep;
  109. {
  110.   int newsize;
  111.   char **oldp_hash, **pe, *p, *q;
  112.   int oldp_used, oldp_size;
  113.   int code, i;
  114.  
  115.   if (*word == 0)
  116.     return (-1);
  117.  
  118.   if (p_used + 1 >= p_thresh)
  119.     {
  120.       newsize = p_nextsize;
  121.       if (newsize < 0 || newsize < p_size)
  122.     return (-1);
  123.  
  124.       oldp_hash = p_hash;
  125.       oldp_used = p_used;
  126.       oldp_size = p_size;
  127.  
  128.       p_hash = (char **) xcalloc ((unsigned) newsize, sizeof (char *));
  129.       p_used = 0;
  130.       p_size = newsize;
  131.       p_thresh = p_size / 2;
  132.       p_end = p_hash + p_size;
  133.       for (i = 0, pe = oldp_hash; i < oldp_size; i++, pe++)
  134.     {
  135.       if (*pe)
  136.         {
  137.           if (p_enter (*pe, 0, 1) < 0)
  138.         {
  139.           p_hash = oldp_hash;
  140.           p_used = oldp_used;
  141.           p_size = oldp_size;
  142.           p_thresh = p_size / 2;
  143.           p_end = p_hash + p_size;
  144.           return (-1);
  145.         }
  146.         }
  147.     }
  148.       if (oldp_hash)
  149.     free ((char *) oldp_hash);
  150.       p_nextsize = nextprime ((unsigned short) (newsize * 2));
  151.     }
  152.   if (word[0] == '!')
  153.     {
  154.       p = word;
  155.       code = hash (p + 1);
  156.     }
  157.   else if (keep)
  158.     {
  159.       if (copy)
  160.     {
  161.       p = (char *) xmalloc ((unsigned) (strlen (word) + 1));
  162.  
  163.       if (copy == 1)
  164.         downcase (p, word);
  165.       else
  166.         (void) strcpy (p, word);
  167.     }
  168.       else
  169.     {
  170.       p = word;
  171.     }
  172.       code = hash (p);
  173.     }
  174.   else
  175.     {
  176.       p = (char *) xmalloc ((unsigned) (strlen (word) + 2));
  177.       p[0] = '!';
  178.       downcase (p + 1, word);
  179.       code = hash (p + 1);
  180.     }
  181.   /* make sure it is not already there */
  182.   pe = p_hash + (code % p_size);
  183.   while ((q = *pe))
  184.     {
  185.       if (*q == '!')
  186.     {
  187.       if (strcmp (q + 1, p) == 0)
  188.         {
  189.           /* he did 'A', now 'I', skip the '!' */
  190.           (*pe)++;
  191.           return (0);
  192.         }
  193.     }
  194.       else if (strcmp (q, p) == 0)
  195.     {
  196.       return (0);
  197.     }
  198.       pe++;
  199.       if (pe == p_end)
  200.     pe = p_hash;
  201.     }
  202.   *pe = p;
  203.   p_used++;
  204.   if (keep)
  205.     p_modified = 1;
  206.   addchars (p);
  207.   return (0);
  208. }
  209.  
  210.  
  211. int
  212. p_load (file, keep)
  213.   char *file;
  214.   int keep;
  215. {
  216.   FILE *f;
  217.   int nwords;
  218.   int c;
  219.   char buf[MAX_WORD_LEN], *p, *start;
  220.  
  221.   int omodified;
  222.  
  223.   omodified = p_modified;
  224.  
  225.   if ((f = fopen (file, "r")) == NULL)
  226.     return (-1);
  227.  
  228.   nwords = 0;
  229.  
  230.   while ((c = getc (f)) != EOF)
  231.     if (c == '\n')
  232.       nwords++;
  233.  
  234.  
  235.   p_nextsize += nextprime ((unsigned) ((nwords + 20) * 2));
  236.  
  237.   rewind (f);
  238.   while (fgets (buf, sizeof buf, f) != NULL)
  239.     {
  240.       if (buf[0] == '#')
  241.     continue;
  242.       downcase (buf, buf);
  243.       start = buf;
  244.       while (isspace (*start))
  245.     start++;
  246.       for (p = start; *p && !isspace (*p); p++)
  247.     ;
  248.       *p = 0;
  249.       if (*start == 0)
  250.     continue;
  251.       addchars (start);
  252.       if (p_enter (start, 1, keep) < 0)
  253.     {
  254.       (void) fclose (f);
  255.       return (-1);
  256.     }
  257.     }
  258.   (void) fclose (f);
  259.   p_modified = omodified;
  260.   return (0);
  261. }
  262.  
  263.  
  264. void
  265. addchars (word)
  266.   char *word;
  267. {
  268.   char *p;
  269.   int c;
  270.  
  271.   for (p = word; *p; p++)
  272.     {
  273.       /* characters above 128 and certain ascii
  274.          * characters can be promoted to be LEXLETTERS
  275.          * if they appear in the ispell.words file
  276.          */
  277.       c = *(unsigned char *) p;
  278.       if (c >= 128 || strchr ("$*+-/_~", c) != NULL)
  279.     {
  280.       (ctbl + 1)[c] |= LEXLETTER;
  281.       if (near_map[c] == 0)
  282.         {
  283.           near_map[c] = 1;
  284.           near_miss_letters[nnear_miss_letters++]
  285.         = c;
  286.         }
  287.     }
  288.     }
  289. }
  290.  
  291.  
  292. char *
  293. make_backup_filename(p)
  294. char *p;
  295. {
  296.   char *bakname = (char *) xmalloc (strlen (p) + 2);
  297.   strcpy(bakname, p);
  298.  
  299. #if defined(MSDOS) || defined(OS2)
  300.   {
  301.   int len, extlen;
  302.   char *q;
  303.   if ((p = strrchr(bakname, '.')) == NULL) 
  304.     p = bakname + strlen(bakname);
  305.   for (q = p; q != bakname; )
  306.     if (strchr(":/\\", *--q)) break;
  307.   extlen = strlen(p); len = p - q;
  308.   if (extlen <= 4 && len <= 8) {   /* then assume FAT */
  309.     switch(extlen) {
  310.     case 0:
  311.       if (len == 8)
  312.     strcat(bakname, ".");
  313.       break;
  314.     case 4:
  315.       p[3] = '\0';
  316.       break;
  317.     }
  318.   }
  319.   }
  320. #endif
  321.   return(strcat(bakname, "~"));
  322. }
  323.  
  324.  
  325. int
  326. p_dump (file)
  327.   char *file;
  328. {
  329.   FILE *f;
  330.   char **pe;
  331.   char *bakname;
  332.  
  333.   if (p_size == 0 || p_modified == 0)
  334.     return (0);
  335.  
  336.   bakname = make_backup_filename(file);
  337.   (void) unlink (bakname);
  338.   if (link (file, bakname) >= 0)
  339.     (void) unlink (file);
  340.  
  341.   if ((f = fopen (file, "w")) == NULL)
  342.     {
  343.       free (bakname);
  344.       return (-1);
  345.     }
  346.  
  347.   pe = p_hash;
  348.  
  349.   while (pe != p_end)
  350.     {
  351.       if (*pe && **pe != '!' && **pe != '#')
  352.     {
  353.       fputs (*pe, f);
  354.       putc ('\n', f);
  355.     }
  356.       pe++;
  357.     }
  358.  
  359.   if (ferror (f))
  360.     {
  361.       (void) fclose (f);
  362.       (void) unlink (file);
  363.       (void) link (bakname, file);
  364.       (void) unlink (bakname);
  365.       free (bakname);
  366.       return (-1);
  367.     }
  368.  
  369.   (void) fclose (f);
  370.   p_modified = 0;
  371.   (void) unlink (bakname);
  372.   free (bakname);
  373.   return (0);
  374. }
  375.  
  376.  
  377. int
  378. p_reload ()
  379. {
  380.   char **pe;
  381.   extern char *privname;
  382.  
  383.   if (privname == (char *) NULL)
  384.     return (-1);
  385.  
  386.   if (p_size)
  387.     {
  388.       pe = p_hash;
  389.       while (pe != p_end)
  390.     {
  391.       if (*pe)
  392.         free (*pe);
  393.       pe++;
  394.     }
  395.       free ((char *) p_hash);
  396.     }
  397.   p_nextsize = 53;
  398.   p_hash = (char **) NULL;
  399.   p_end = (char **) NULL;
  400.   p_size = 0;
  401.   p_used = 0;
  402.   p_thresh = 0;
  403.   p_modified = 0;
  404.   return (p_load (privname, 1));
  405. }
  406.  
  407. #if 0
  408. main ()
  409. {
  410.   char buf[100];
  411.   char *p;
  412.   if (p_load ("testpriv", 1) < 0)
  413.     (void) printf ("couldn't load testpriv\n");
  414.  
  415.   while (gets (buf) != NULL)
  416.     {
  417.       switch (buf[0])
  418.     {
  419.     case 'l':
  420.       p = buf + 2;
  421.       if (p_lookup (p, 0))
  422.         (void) printf ("%s: ok\n", p);
  423.       else
  424.         (void) printf ("%s: not found\n", p);
  425.       break;
  426.     case 'i':
  427.     case 'a':
  428.       p = buf + 2;
  429.       while (*p)
  430.         {
  431.           if (isupper (*p))
  432.         *p = _tolower (*p);
  433.           p++;
  434.         }
  435.       p = buf + 2;
  436.       if (p_enter (p, 1, buf[0] == 'i' ? 1 : 0) < 0)
  437.         (void) printf ("enter failed\n");
  438.       else
  439.         (void) printf ("ok\n");
  440.       break;
  441.     default:
  442.       (void) printf ("unknown cmd %s\n", buf);
  443.       break;
  444.     }
  445.     }
  446.  
  447.   if (p_dump ("testpriv") < 0)
  448.     (void) printf ("dump failed\n");
  449.  
  450. }
  451.  
  452. #endif
  453.