Logo Search packages:      
Sourcecode: canna version File versions  Download package

dd.c

/* Copyright 1994 NEC Corporation, Tokyo, Japan.
 *
 * Permission to use, copy, modify, distribute and sell this software
 * and its documentation for any purpose is hereby granted without
 * fee, provided that the above copyright notice appear in all copies
 * and that both that copyright notice and this permission notice
 * appear in supporting documentation, and that the name of NEC
 * Corporation not be used in advertising or publicity pertaining to
 * distribution of the software without specific, written prior
 * permission.  NEC Corporation makes no representations about the
 * suitability of this software for any purpose.  It is provided "as
 * is" without express or implied warranty.
 *
 * NEC CORPORATION DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN 
 * NO EVENT SHALL NEC CORPORATION BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF 
 * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 
 * OTHER TORTUOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 
 * PERFORMANCE OF THIS SOFTWARE. 
 */

#if !defined(lint) && !defined(__CODECENTER__)
static char rcsid[]="$Id: dd.c,v 1.5 2003/09/17 08:50:52 aida_s Exp $";
#endif
/*LINTLIBRARY*/

#include    "RKintern.h"

#ifdef __CYGWIN32__
#include <fcntl.h> /* for O_BINARY */
#endif

#include <errno.h>

#include    <stdio.h>
/* #include <pwd.h> */
#include <time.h>
#ifdef __EMX__
#include <io.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>

#define     Calloc            calloc
#define cx_gwt          cx_extdata.ptr
#define     STRCMP(d, s)      strcmp((char *)(d), (char *)(s))

#define RK_READABLE 'r'
#define RK_WRITABLE 'w'

/*
 * DD privates 
 */
static struct DM  *_RkCreateDM();
static void       _RkFreeDM();
static struct DM  *_RkAllocDM();
static struct DF  *_RkCreateDF();
static void       _RkFreeDF();
static struct DF  *_RkAllocDF();

static struct DD  *_RkCreateDD();
static void       _RkFreeDD();
static struct DD  *_RkLookupDD();
static struct DD  *_RkReadDD();
static struct DD  *_RkOpenDD();
static int        _RkCountDDP();
static struct DD  **_RkAppendDDP();

char *
allocStr(s)
     char   *s;
{
  char      *d = (char *)0;
  int len;
  
  if ((len = strlen(s)) && (d = malloc(len + 1))) {
    (void)strncpy(d, s, len);
    d[len] = (char)0;
  }
  return(d);
}

/*
 * DM
 */
static
struct DM   *
_RkCreateDM(df, dicname, nickname, class)
     struct DF          *df;
     unsigned char      *dicname;
     unsigned char      *nickname;
     int          class;
{
  struct DM *dm;
    
  dm = (struct DM *)Calloc(1, sizeof(struct DM));
  if (dm) {
    dm->dm_next = dm->dm_prev = dm;
    dm->dm_file = df;
    dm->dm_dicname  = allocStr((char *)dicname);
    if (dm->dm_dicname) {
      dm->dm_nickname = allocStr((char *)nickname);
      if (dm->dm_nickname) {
      dm->dm_class = class;
      dm->dm_flags = dm->dm_packbyte = dm->dm_rcount = 0;
      dm->dm_gram = (struct RkGram *)0;
      dm->dm_extdata.ptr = (pointer)0;
      dm->dm_rut = (struct RUT *)0;
      dm->dm_nv = (struct NV *)0;
      return dm;
      }
      free((char *)dm->dm_dicname);
    }
    free((char *)dm);
  }
  return 0;
}

static
void
_RkFreeDM(dm)
     struct DM    *dm;
{
    if (dm) {
      dm->dm_next->dm_prev = dm->dm_prev;
      dm->dm_prev->dm_next = dm->dm_next;
      if (dm->dm_dicname)
          (void)free((char *)dm->dm_dicname);
      if (dm->dm_nickname)
          (void)free((char *)dm->dm_nickname);
      (void)free((char *)dm);
    };
}

static
struct DM *
_RkAllocDM(df, dicname, nickname, class)
     struct DF          *df;
     unsigned char      *dicname;
     unsigned char      *nickname;
     int          class;
{
  struct DM *m, *mh = &df->df_members;

  for (m = mh->dm_next; m != mh; m = m->dm_next) {
    if (!STRCMP(m->dm_dicname,  dicname)) {
      return m;
    }
  }
  m = _RkCreateDM(df, dicname, nickname, class);
  if (m) {
    m->dm_next = mh;
    m->dm_prev = mh->dm_prev;
    mh->dm_prev = m;
    m->dm_prev->dm_next = m;
  }
  return(m);
}

/*
 * DF
 */
static
struct DF *
_RkCreateDF(dd, lnk, type)
     struct DD          *dd;
     unsigned char      *lnk;
     int          type;
{
  struct DF *df;
    
  df = (struct DF *)Calloc(1, sizeof(struct DF));
  if (df) {
    struct DM     *dm = &df->df_members;
    
    df->df_next = df->df_prev = df;
    df->df_direct = dd;
    dm->dm_next = dm->dm_prev = dm;
    
    if (!(df->df_link = allocStr((char *)lnk))) {
      (void)free(df);
      return(0);
    };
    df->df_rcount = 0;
    df->df_type  = type;
    df->df_extdata.ptr = (pointer)0;
  };
  return(df);
}

static
void
_RkFreeDF(df)
     struct DF    *df;
{
  struct DM *m, *n;

  if (df) {
    struct DM     *mh = &df->df_members;
    
    /* remove all members in this file */
    for (m = mh->dm_next; m != mh; m = n) {
      n = m->dm_next;
      _RkFreeDM(m);
    };
    /* unlink from directory list */
    df->df_next->df_prev = df->df_prev;
    df->df_prev->df_next = df->df_next;
    if (df->df_link)
      (void)free((char *)df->df_link);
    (void)free((char *)df);
  };
}

static
struct DF   *
_RkAllocDF(dd, lnk, type)
     struct DD          *dd;
     unsigned char      *lnk;
{
  struct DF *f;
  struct DF *fh = &dd->dd_files;

  for (f = fh->df_next; f != fh; f = f->df_next) {
    if (!STRCMP(f->df_link,  lnk)) {
      return(f);
    }
  }
  f = _RkCreateDF(dd, lnk, type);
  if (f) {
    f->df_next = fh;
    f->df_prev = fh->df_prev;
    fh->df_prev = f;
    f->df_prev->df_next = f;
  };
  return(f);
}

int
_RkRealizeDF(df)
     struct DF    *df;
{
  struct DD *dd = df->df_direct;
  char            *pathname;
  unsigned long oldmask;
  int t;
    
  _RkRealizeDD(dd);
  /* create path filename */
  pathname = _RkCreatePath(df->df_direct, df->df_link);
  if (pathname) {
    oldmask = umask(2);
    /* create a file */
    t = close(creat(pathname, CREAT_MODE));
    (void)free(pathname);
    (void)umask(oldmask);
    if (t >= 0) {
      return 0;
    }
  }
  return -1;
}

static int
_RkParseDicsDir(line, lnk, member, nickname, dftype, dmclass,
            r_return, w_return)
char  *line;
char  *lnk;
char  *member;
char  *nickname;
int   *dftype;
int   *dmclass;
int *r_return, *w_return; /* アクセス権を返す所 */
{
  char      *s, *d, *t, par, ch;
  int count;

  *dftype  = -1;
  *dmclass = -1;
  *r_return = *w_return = 0; /* 権利無し */
  if (!isalpha(line[0])) 
    return -1;

  /* parse line %s.s(%s.%s)   -%s--%c%c- */

  for (s = line; *s && isspace(*s);) {
    s++;
  }
  if (!*s)
    return -1;

  /* link name */
  for (d = lnk, count = 0; *s && *s != '('; count++) {
    if (count < RK_LINK_BMAX) {
      *d++ = *s++;
    } else {
      return -1;
    }
  }
  if (!count)
    return -1;
  if (count++ < RK_LINK_BMAX) {
    *d = 0;
  }
  if (!*s++) 
    return -1;
  if (count > RK_LINK_BMAX)
    return -1;
  if (!(t = (char *)strrchr(lnk, '.')))
    return -1;
  if (!STRCMP(t, ".d") || !STRCMP(t, ".cbd"))
    *dftype = DF_PERMDIC;
  else if (!STRCMP(t, ".t") || !STRCMP(t, ".ctd"))
    *dftype = DF_TEMPDIC;
  else if (!STRCMP(t, ".fq") || !STRCMP(t, ".cld"))
    *dftype = DF_FREQDIC;
  else if (!STRCMP(t, ".ruc"))  
    *dftype = DF_RUCDIC;
  else            
    return -1;
  /* member name */
  for (d = member, count = 0; *s && *s != ')'; count++) {
    if (count < RK_MEMBER_BMAX) {
      *d++ = *s++;
    } else {
      return -1;
    }
  }
  if (!count)
    return -1;
  if (count++ < RK_MEMBER_BMAX)
    *d = 0;
  if (!*s++)
    return -1;
  if (count > RK_MEMBER_BMAX)
    return -1;
  if (!(t = (char *)strrchr(member, '.')))
    return -1;
  if (!STRCMP(t, ".mwd"))   
    *dmclass = ND_MWD;
  else if (!STRCMP(t, ".swd"))   
    *dmclass = ND_SWD;
  else if (!STRCMP(t, ".pre"))   
    *dmclass = ND_PRE;
  else if (!STRCMP(t, ".suc"))   
    *dmclass = ND_SUC;
  else
    return -1;
  /* nickname */
  for (; *s && isspace(*s);) {
    s++;
  }
  if (!(par = *s++))
    return -1;

  for (d = nickname, count = 0; *s && *s != par; count++) {
    if (count < RK_NICK_BMAX) {
      *d++ = *s++;
    } else {
      return -1;
    }
  }
  if (!count)
    return -1;
  if (count++ < RK_NICK_BMAX)
    *d = 0;
  if (!*s++)
    return -1;
  if (count > RK_NICK_BMAX)
    return -1;

  *w_return = 1; /* 下位互換のためここまでしかない場合は writable にする */

  while ((ch = *s) && ch != par) {
    s++;/* 1 フィールド読み飛ばし */
  }

  if (*s++ /* == par になっているわけ */) {
    /* アクセス権関連 */
    *w_return = 0;
    while ((ch = *s) && ch != par) {
      if (ch == RK_READABLE) {
      *r_return = 1;
      }
      else if (ch == RK_WRITABLE) {
      *w_return = 1;
      } else {
      return -1;
      }
      s++;
    }
  }

  return 0;
}

/*
 * DD - dictonary directory record
 */
static
struct DD   *
_RkCreateDD(path, name)
     unsigned char      *path, *name;
{
  struct DD *dd;
    
  dd = (struct DD *)Calloc(1, sizeof(struct DD));
  if (dd) {
    dd->dd_next = dd->dd_prev = dd;
    dd->dd_path = allocStr((char *)path);
    if (dd->dd_path) {
      dd->dd_name = allocStr((char *)name);
      if (dd->dd_name) {
      dd->dd_rcount = 0;      
      dd->dd_files.df_next = dd->dd_files.df_prev = &dd->dd_files;
      dd->dd_flags = 0;
      dd->dd_text.ddt_next = dd->dd_text.ddt_prev = &dd->dd_text;
      return dd;
      }
      free((char *)dd->dd_path);
    }
    free((char *)dd);
  }
  return (struct DD *)0;
}

static 
void
_RkFreeDD(dd)
     struct DD    *dd;
{
  struct DF *f, *g;
  struct DF *fh = &dd->dd_files;
  struct DDT      *ddLines;
  struct DDT      *p, *q;

  if (dd) {
    for (f = fh->df_next; f != fh; f = g) {
      g = f->df_next;
      _RkFreeDF(f);
    };
    dd->dd_next->dd_prev = dd->dd_prev;
    dd->dd_prev->dd_next = dd->dd_next;
    if (dd->dd_path)
      (void)free((char *)dd->dd_path);
    if (dd->dd_name)
      (void)free((char *)dd->dd_name);

    ddLines = &dd->dd_text;
    for (p = ddLines->ddt_next; p != ddLines; p = q) {
      q = p->ddt_next;
      p->ddt_next->ddt_prev = p->ddt_prev;
      p->ddt_prev->ddt_next = p->ddt_next;
      if (p->ddt_spec)
      (void)free((char *)p->ddt_spec);
      (void)free((char *)p);
    };
    (void)free((char *)dd);
  };
}
static
struct DD   *
_RkLookupDD(dd, name)
     struct DD    *dd;
     unsigned char      *name;
{
  struct DD       *d;

  for (d = dd->dd_next; d != dd; d = d->dd_next)
    if (!STRCMP(d->dd_name,  name))
      return d;
  return (struct DD *)0;
}

/* _RkReadDD
 *    read a DD directory using dics.dir file.
 */
static
struct DD   *
_RkReadDD(name)
     char   *name;
{
  char            *dics_dir = "/dics.dir";
  struct DD *dd = (struct DD *)0;
  struct DF       *df;
  struct DM       *dm;
  struct DDT            *ddLines;
  struct DDT            *ddt;
  struct RkParam  *sx = RkGetSystem();
  int r, w;
  int fdes;
  FILE            *fp;

#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char            direct[RK_PATH_BMAX];
  char            file[RK_PATH_BMAX];
  char            path[RK_PATH_BMAX];
  unsigned char   line[RK_LINE_BMAX];
  unsigned char   lnk[RK_LINK_BMAX+1];
  unsigned char   member[RK_MEMBER_BMAX+1];
  unsigned char   nickname[RK_NICK_BMAX+1];
#else
  char *direct, *file, *path;
  unsigned char *line, *lnk, *member, *nickname;
  direct = malloc(RK_PATH_BMAX);
  file = malloc(RK_PATH_BMAX);
  path = malloc(RK_PATH_BMAX);
  line = (unsigned char *)malloc(RK_LINE_BMAX);
  lnk = (unsigned char *)malloc(RK_LINK_BMAX + 1);
  member = (unsigned char *)malloc(RK_MEMBER_BMAX + 1);
  nickname = (unsigned char *)malloc(RK_NICK_BMAX + 1);
  if (!direct || !file || !path || !line || !lnk || !member || !nickname) {
    if (direct) (void)free(direct);
    if (file) (void)free(file);
    if (path) (void)free(path);
    if (line) (void)free((char *)line);
    if (lnk) (void)free((char *)lnk);
    if (member) (void)free((char *)member);
    if (nickname) (void)free((char *)nickname);
    return dd;
  }
#endif
   
  /* create dd even if there is no directory or dics.dir file */
  (void)strcpy(path, sx->ddhome);
  (void)strcat(path, "/");
  (void)strcat(path, name);
  dd = _RkCreateDD((unsigned char *)path, (unsigned char *)name);
  if (!dd) {
    goto return_dd;
  }
  /* jisho table ga aruka ? */
  if (strlen(path) + strlen(dics_dir) + 1 >= RK_PATH_BMAX) {
    dd = (struct DD *)0;
    goto return_dd;
  }
  (void)strcpy(direct, path);
  (void)strcat(direct, dics_dir);

  /* check for accessing right */
  if ((fdes = open(direct, 0)) < 0) { /* no file? */
    dd->dd_flags |= DD_WRITEOK;
  }
  else {
    struct stat buf;

    if (fstat(fdes, &buf) == 0) {
      if (buf.st_mode & 004) { /* if readable for others */
      dd->dd_flags |= DD_READOK;
      }
    }
    close(fdes);
    if (!close(open(direct, 2))) {
      dd->dd_flags |= DD_WRITEOK;
    }
  }

#ifdef __EMX__
  fp = fopen(direct, "rt");
#else
  fp = fopen(direct, "r");
#endif
  if (!fp) {
    goto return_dd;
  }
  ddLines = &dd->dd_text;
  /* read dics_dir lines */
  while (fgets((char *)line, RK_LINE_BMAX, fp)) {
    int           dftype, dmclass;

    ddt = (struct DDT *)malloc(sizeof(struct DDT));
    if (!ddt)
      continue;

    ddt->ddt_spec = malloc(strlen((char *)line) + 2); /* 2 for \n\0 */
    if (!ddt->ddt_spec)
      {
      free(ddt);
      continue;
      };
    {
      int len = strlen((char *)line);
      if (line[len - 1] == '\n') {
      line[len - 1] = '\0';
      }
    }
    strcpy(ddt->ddt_spec, (char *)line);

    ddt->ddt_next = ddLines;
    ddt->ddt_prev = ddLines->ddt_prev;
    ddt->ddt_status = 1;
    ddLines->ddt_prev = ddt;
    ddt->ddt_prev->ddt_next = ddt;

    if (_RkParseDicsDir(ddt->ddt_spec, (char *)lnk, (char *)member,
                  (char *)nickname, &dftype, &dmclass, &r, &w) < 0) {
      continue;
    }

    if (strlen((char *)path) + strlen((char *)lnk) + 1 >= RK_PATH_BMAX)
      continue;
    (void)strcpy(file, path);
    (void)strcat(file, "/");
    (void)strcat(file, (char *)lnk);
    if (close(open(file, 0)) < 0)
      continue;
    df = _RkAllocDF(dd, lnk, dftype);
    if (df) {
      dm = _RkAllocDM(df, member, nickname, dmclass);
      if (dm) {
      dm->dm_line = ddt;
      if (r) {
        dm->dm_flags |= DM_READOK;
      }
      if (w) {
        dm->dm_flags |= DM_WRITEOK;
      }
      ddt->ddt_status = 0;
      };
    };
  };
  (void)fclose(fp);

 return_dd:
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(direct);
  (void)free(file);
  (void)free(path);
  (void)free((char *)line);
  (void)free((char *)lnk);
  (void)free((char *)member);
  (void)free((char *)nickname);
#endif
  return dd;
}

static
struct DD   *
_RkOpenDD(name)
     char   *name;
{
  struct RkParam  *sx = RkGetSystem();
  struct DD       *dd;
  struct DD       *knownDD = &sx->dd;

  dd = _RkLookupDD(knownDD, (unsigned char *)name);
  if (dd)
    return dd;
  dd = _RkReadDD(name);
  /* link to the known list */
  if (dd) {
    dd->dd_next = knownDD;
    dd->dd_prev = knownDD->dd_prev;
    knownDD->dd_prev = dd;
    dd->dd_prev->dd_next = dd;
  };
  return dd;
}

char *
_RkCreatePath(dd, name)
     struct DD    *dd;
     char   *name;
{
  unsigned  sz;
  char        *ddname;
    
  if (!dd || !dd->dd_path || !name)
    return (char *)0;
  sz = strlen(dd->dd_path) + strlen(name) + 2;
  ddname = malloc(sz);
  if (ddname)  {
    (void)strcpy(ddname, dd->dd_path);
    (void)strcat(ddname, "/");
    (void)strcat(ddname, name);
  };
  return ddname;
}

char *
_RkCreateUniquePath(dd, proto)
     struct DD    *dd;
     char   *proto;
{
  static char     newLinkName[RK_LINK_BMAX];
  unsigned  i;
    
  /* now checking ... */
  if (!dd || !dd->dd_path || !proto)
    return (char *)0;
  /* create directory */
  if (_RkRealizeDD(dd) < 0)
    return (char *)0;
  /* try at most 100 times */
  for (i = 1; i < 100; i++) {
    int           count;
    struct DF           *f;
    struct DF           *fh = &dd->dd_files;
    unsigned long       oldmask;
    char          *filename;
    
    count = 0;
    sprintf(newLinkName, proto, i);
    for (f = fh->df_next; f != fh; f = f->df_next)
      if (!STRCMP(f->df_link,  newLinkName))
      count++;
    if (count)
      continue;
    filename = _RkCreatePath(dd, newLinkName);
    if (filename) {
      oldmask = umask(2);
      
      if (close(creat(filename, CREAT_MODE)) < 0)
      count++;
      (void)free(filename);
      (void)umask(oldmask);
      if (!count)
      return newLinkName;
    };
  };
  return (char *)0;
}

char  *
_RkMakePath(df)
     struct DF       *df;
{
  if (df)
    return _RkCreatePath(df->df_direct, df->df_link);
  else
    return (char *)0;
}

int
_RkRealizeDD(dd)
     struct DD    *dd;
{
  struct DDT            *ddLines;
  struct DDT            *ddt;
  int             n;
  int ret = -1;
  int tmpres;
  int             fdes;
  long            tloc;
#ifdef __EMX__
  struct stat           statbuf;
#endif

#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char            whattime[RK_LINE_BMAX];
  char            header[RK_LINE_BMAX];
  char            dicsdir[RK_PATH_BMAX];
  char            backup[RK_PATH_BMAX];
#else
  char *whattime, *header, *dicsdir, *backup;
  whattime = malloc(RK_LINE_BMAX);
  header = malloc(RK_LINE_BMAX);
  dicsdir = malloc(RK_PATH_BMAX);
  backup = malloc(RK_PATH_BMAX);
  if (!whattime || !header || !dicsdir || !backup) {
    if (whattime) (void)free(whattime);
    if (header) (void)free(header);
    if (dicsdir) (void)free(dicsdir);
    if (backup) (void)free(backup);
    return ret;
  }
#endif

  /* create directory if needed */
  if (mkdir(dd->dd_path, MKDIR_MODE) < 0 &&
      errno != EEXIST) {
    goto return_ret;
  }
  /* dics.dir */
  (void)strcpy(dicsdir, dd->dd_path);
  (void)strcat(dicsdir, "/dics.dir");
  backup[0] = 0;
  tmpres = close(open(dicsdir, 0));
  if (tmpres >= 0) {
    (void)strcpy(backup, dd->dd_path);
    (void)strcat(backup, "/#dics.dir");
#ifdef HAVE_RENAME
#ifdef __EMX__
    unlink(backup);
#endif
    if (rename(dicsdir, backup)) {
      goto return_ret;
    }
#else
    unlink(backup);
    if (link(dicsdir, backup) < 0) {
      goto return_ret;
    }
    unlink(dicsdir);
#endif /* !HAVE_RENAME */
  };
  /* create dics.dir */
    
  if ((fdes = creat(dicsdir, CREAT_MODE)) < 0) {
    if (backup[0]) {
#ifdef HAVE_RENAME
#ifdef __EMX__
      unlink(dicsdir);
#endif
      rename(backup, dicsdir);
#else
      unlink(dicsdir);
      if (link(backup, dicsdir) == 0) {
      unlink(backup);
      }
#endif
    }
    goto return_ret;
  };
#ifdef __CYGWIN32__
  setmode(fdes, O_BINARY);
#endif
/* header */
  tloc = time(0);
  strcpy(whattime, ctime(&tloc));
  whattime[strlen(whattime)-1] = 0;
  (void)strcpy(header, "#CANNA dics.dir [");
  (void)strcat(header, whattime);
  (void)strcat(header, "] ");
  (void)strcat(header, dd->dd_name);
  (void)strcat(header, "\n");
  n = strlen(header);
  tmpres = write(fdes, header, n);
  if (tmpres != n) {
    if (backup[0]) {
#ifdef HAVE_RENAME
#ifdef __EMX__
      unlink(dicsdir);
#endif
      rename(backup, dicsdir);
#else
      unlink(dicsdir);
      if (link(backup, dicsdir) == 0) {
      unlink(backup);
      }
#endif
    }
    else
      unlink(dicsdir);
    close(fdes);
    goto return_ret;
  };
  /* fill up bodies */
  ddLines = &dd->dd_text;
  for (ddt = ddLines->ddt_next; ddt != ddLines; ddt = ddt->ddt_next)
    if (strncmp(ddt->ddt_spec, "#CANNA ",  7)) {
      n = strlen(ddt->ddt_spec);

      ddt->ddt_spec[n] = '\n';
      tmpres = write(fdes, ddt->ddt_spec, n + 1);
      if (tmpres > 0) {
      tmpres--; /* for \n */
      }
      
      ddt->ddt_spec[n] = '\0';

      if (tmpres != n) {
      if (backup[0]) {
#ifdef HAVE_RENAME
#ifdef __EMX__
        unlink(dicsdir);
#endif
        rename(backup, dicsdir);
#else
        unlink(dicsdir);
        if (link(backup, dicsdir) == 0) {
          unlink(backup);
        }
#endif
      }
      else
        unlink(dicsdir);
      close(fdes);
      goto return_ret;
      };
    };
  close(fdes);
  /* change owner
  if (pw)
  chown(dicsdir, getuid(), pw->pw_gid);
  */
  ret = 0;

 return_ret:
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(whattime);
  (void)free(header);
  (void)free(dicsdir);
  (void)free(backup);
#endif
  return ret;
}

/*
 * DDP
 */
int
_RkIsInDDP(ddp, dd)
     struct DD    **ddp, *dd;
{
  while (*ddp) 
    if (*ddp++ == dd)
      return 1;
  return 0;
}

static
int
_RkCountDDP(ddp)
     struct DD    **ddp;
{
  int count = 0;

  if (ddp)
    while (ddp[count])  count++;
  return count;
}
struct DD   **
_RkCopyDDP(ddp)
     struct DD    **ddp;
{
  struct DD **new = (struct DD **)0;
  int       i;
  struct DD *dd;

  if (ddp) {
    int     count = _RkCountDDP(ddp);

    new = (struct DD **)Calloc(count + 1, (unsigned)sizeof(struct DD *));
    if (new)
      for (i = 0; (dd = new[i] = ddp[i]) != (struct DD *)0 ; i++) 
      dd->dd_rcount++;
  };
  return new;
}
static
struct DD   **
_RkAppendDDP(ddp, dd)
     struct DD    **ddp;
     struct DD    *dd;
{
  struct DD **new;
  int       i;
  int       count = _RkCountDDP(ddp);

  new = (struct DD **)Calloc(count + 2, (unsigned)sizeof(struct DD *));
  if (new) {
    if (ddp) {
      for (i = 0; i < count; i++) new[i] = ddp[i];
      (void)free((char *)ddp);
    };
    new[count++] = dd;
    new[count] = (struct DD *)0;
    dd->dd_rcount++;
  } else
    new = ddp;
  return new;
}

struct DD   **
_RkCreateDDP(ddpath)
     char         *ddpath;
{
  char            *d, *s;
  struct DD       *dd;
  struct DD **ddp  = (struct DD **)0;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char dir[RK_PATH_BMAX + 1];
#else
  char *dir = malloc(RK_PATH_BMAX + 1);
  if (!dir) {
    return ddp;
  }
#endif
  
  for (s = ddpath; *s; ) {
    int           count;

    for (;*s && isspace(*s);) {
      s++;
    }
    if (!*s)
      break;
    for (d = dir, count = 0; *s; count++) 
      if (*s == ':') {
      s++;
      break;
      } else {
      if (count < RK_PATH_BMAX)
        *d++ = *s;
      s++;
      };
    *d = 0;
    dd = _RkOpenDD(dir);
    if (dd) 
      ddp = _RkAppendDDP(ddp, dd);
  };
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(dir);
#endif
  return ddp;
}

void
_RkFreeDDP(ddp)
     struct DD    **ddp;
{
  struct DD *dd;
  int       i;
  
  if (ddp) {
    for (i = 0; (dd = ddp[i]) != (struct DD *)0 ; i++)
      if (--dd->dd_rcount == 0) {
      _RkFreeDD(dd);
      };
    (void)free((char *)ddp);
  };
}

/* _RkSearchDDP/Q
 *    search dictionary file by nickname 
 */
struct DM   *
_RkSearchDDP(ddp, name)
     struct DD    **ddp;
     char   *name;
{
  struct DD *dd;
  struct DF *f, *fh;
  struct DM *m, *mh;
  int       i;

  if (ddp) {
    for (i = 0; (dd = ddp[i]) != (struct DD *)0 ; i++) {
      fh = &dd->dd_files;
      for (f = fh->df_next; f && (f != fh); f = f->df_next) {
      if (f->df_type == DF_FREQDIC) {
        /* 同じディレクトリ階層では .fq から探す */
        mh = &f->df_members;
        for (m = mh->dm_next; m != mh; m = m->dm_next) {
          if (!STRCMP(m->dm_nickname, name)) {
            return m;
          }
        }
      }
      }
      fh = &dd->dd_files;
      for (f = fh->df_next; f && (f != fh); f = f->df_next) {
      if (f->df_type != DF_RUCDIC && f->df_type != DF_FREQDIC) {
        mh = &f->df_members;
        for (m = mh->dm_next ; m != mh; m = m->dm_next) {
          if (!STRCMP(m->dm_nickname, name)) {
            return m;
          }
        }
      }
      }
    }
  }
  return (struct DM *)0;
}

/* _RkSearchDDQ
   あるタイプの辞書だけ探して返す
 */

struct DM   *
_RkSearchDDQ(ddp, name, type)
     struct DD    **ddp;
     char   *name;
     int    type;
{
  struct DD *dd;
  struct DF *f, *fh;
  struct DM *m, *mh;
  int       i;

  if (ddp) {
    for (i = 0; (dd = ddp[i]) != (struct DD *)0 ; i++) {
      fh = &dd->dd_files;
      for (f = fh->df_next; f && (f != fh); f = f->df_next)
      if (f->df_type == (unsigned)type) {
        mh = &f->df_members;
        for (m = mh->dm_next; m != mh; m = m->dm_next) {
          if (!STRCMP(m->dm_nickname, name)) 
            return(m);
        };
      };
    };
  };
  return((struct DM *)0);
}

/* 
 _RkSearchUDDP()
  最初に見付かるのがシステム辞書にあるやつかどうかを判断しながら返す
 */

struct DM   *
_RkSearchUDDP(ddp, name)
     struct DD          **ddp;
     unsigned char      *name;
{
  struct DM *dm = _RkSearchDDP(ddp, (char *)name);
    
  if (dm && STRCMP(dm->dm_file->df_direct->dd_name, SYSTEM_DDHOME_NAME)) {
    return dm;
  }
  return((struct DM *)0);
}

/* 辞書メンバ名で辞書を探す

  学習ファイルは除外して探す
 */

struct DM   *
_RkSearchDDMEM(ddp, name)
     struct DD    **ddp;
     char   *name;
{
  struct DD *dd;
  struct DF *f, *fh;
  struct DM *m, *mh;
  int       i;

  if (ddp) {
    for (i = 0; (dd = ddp[i]) != (struct DD *)0 ; i++) {
      fh = &dd->dd_files;
      for (f = fh->df_next; f && (f != fh); f = f->df_next) {
      if (f->df_type != DF_FREQDIC && f->df_type != DF_RUCDIC) {
        mh = &f->df_members;
        for (m = mh->dm_next; m != mh; m = m->dm_next) {
          if (!STRCMP(m->dm_dicname, name)) {
            return m;
          }
        }
      }
      }
    }
  }
  return (struct DM *)0;
}

/*
  _RkSearchDicWithFreq -- 辞書(学習辞書を含む)を探し返す。

  ddpath の先頭から順に学習ファイルあるいは辞書をさがし、みつかったの
  を返す。学習ファイルがみつかった場合には学習ファイルの元辞書を探して
  それを dm に返し、学習ファイル自身は qmp の先に格納して返す。

 */

struct DM *
_RkSearchDicWithFreq(ddpath, name, qmp)
struct DD **ddpath;
char *name;
struct DM **qmp;
{
  struct DD *udd[2];
  struct DM *dm, *qm;

  udd[1] = (struct DD *)0;

  *qmp = (struct DM *)0;
  while (*ddpath) {
    udd[0] = *ddpath;
    qm = _RkSearchDDQ(udd, name, DF_FREQDIC);
    if (qm) {
      *qmp = qm;
      return _RkSearchDDMEM(ddpath, qm->dm_dicname);
    }
    dm = _RkSearchDDP(udd, name);
    if (dm) {
      return dm;
    }
    ddpath++;
  }
  return (struct DM *)0;
}

/* DMcheck

   DMcreate で name を第3引数に付けていた時のチェックを独立させた。

   return value;
      1: OK
      0: bad
 */

DMcheck(spec, name)
char *spec;
char *name;
{
  int dftype, dmclass;
  int r, w, ret;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char lnk[RK_LINK_BMAX+1];
  char member[RK_MEMBER_BMAX+1];
  char nickname[RK_NICK_BMAX+1];
#else
  char *lnk, *member, *nickname;
  lnk = malloc(RK_LINK_BMAX + 1);
  member = malloc(RK_MEMBER_BMAX + 1);
  nickname = malloc(RK_NICK_BMAX + 1);
  if (!lnk || !member || !nickname) {
    if (lnk) (void)free(lnk);
    if (member) (void)free(member);
    if (nickname) (void)free(nickname);
    return 0;
  }
#endif

  if (_RkParseDicsDir(spec, lnk, member, nickname, &dftype, &dmclass,
                  &r, &w) < 0 ||
      STRCMP(nickname, name)) {
    ret = 0;
  }
  else {
    ret = 1;
  }
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(lnk);
  (void)free(member);
  (void)free(nickname);
#endif
  return ret;
}

/* DMcreate
 *    create a new member under dd 
 *    DMcreate does not create an actual dictionary file.
 */
struct DM   *
DMcreate(dd, spec)
     struct DD          *dd;
     char         *spec;
{
  int       dftype, dmclass;
  struct DF *df;
  struct DM *dm = (struct DM *)0;
  struct DDT      *ddt;
  struct DDT      *ddLines = &dd->dd_text;
  int r, w;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char            lnk[RK_LINK_BMAX+1];
  char            member[RK_MEMBER_BMAX+1];
  char            nickname[RK_NICK_BMAX+1];
#else
  char *lnk, *member, *nickname;
  lnk = malloc(RK_LINK_BMAX + 1);
  member = malloc(RK_MEMBER_BMAX + 1);
  nickname = malloc(RK_NICK_BMAX + 1);
  if (!lnk || !member || !nickname) {
    if (lnk) (void)free(lnk);
    if (member) (void)free(member);
    if (nickname) (void)free(nickname);
    return dm;
  }
#endif

  if (_RkParseDicsDir(spec, lnk, member, nickname, &dftype, &dmclass,
                  &r, &w) >= 0) {
    int len = strlen(spec);
    if (spec[len - 1] == '\n') {
      spec[len - 1] = '\0';
    }

    ddt = (struct DDT *)malloc(sizeof(struct DDT));
    if (ddt) {
      ddt->ddt_spec = malloc(strlen(spec) + 3); /* 3 for \r\n\0 */
      if (ddt->ddt_spec) {
      strcpy(ddt->ddt_spec, spec);
      df = _RkAllocDF(dd, (unsigned char *)lnk, dftype);
      if (df) {
        dm = _RkAllocDM(df, (unsigned char *)member,
                    (unsigned char *)nickname, dmclass);
        if (dm) {
          ddt->ddt_next = ddLines;
          ddt->ddt_prev = ddLines->ddt_prev;
          ddLines->ddt_prev = ddt;
          ddt->ddt_prev->ddt_next = ddt;
          ddt->ddt_status = 0;
          dm->dm_line = ddt;
          dm->dm_flags |= DM_WRITEOK; /* default access right */
          goto return_dm;
        }
        _RkFreeDF(df);
      }
      (void)free((char *)ddt->ddt_spec);
      }
      (void)free((char *)ddt);
    }
  }
 return_dm:
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(lnk);
  (void)free(member);
  (void)free(nickname);
#endif
  return(dm);
}

int
DMremove(dm)
     struct DM    *dm;
{
  struct DF *df = dm->dm_file;
  struct DDT      *ddt = dm->dm_line;


  /* free up dirs.dic line */
   if (ddt) {
     ddt->ddt_next->ddt_prev = ddt->ddt_prev;
     ddt->ddt_prev->ddt_next = ddt->ddt_next;
     if (ddt->ddt_spec)
       free((char *)ddt->ddt_spec);
     free((char *)ddt);
   };
  /* free dm itself */
  _RkFreeDM(dm);
  if (df) {
    struct DM     *mh = &df->df_members;
    
    if (mh == mh->dm_next)
      _RkFreeDF(df);
  };
  return 0;
}

int
DMrename(dm, nickname)
     struct DM          *dm;
     unsigned char      *nickname;
{
  struct DF *df = dm->dm_file;
  struct DDT      *ddt = dm->dm_line;
  char            *new_spec;
  char            *new_nick;
  char            member[5];
  char *dicname = (char *)0;
  int ret = -1;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char            spec[RK_LINE_BMAX];
#else
  char *spec = malloc(RK_LINE_BMAX);
  if (!spec) {
    return ret;
  }
#endif

  if (!df || !df->df_link || !dm->dm_file || !ddt || !ddt->ddt_spec)
    goto return_ret;
  if (df->df_type == DF_FREQDIC) {
    dicname = dm->dm_dicname;
  }
  switch (dm->dm_class) {
  default:
  case ND_MWD:
    (void)strcpy(member, ".mwd");
    break;
  case ND_SWD:
    (void)strcpy(member, ".swd");
    break;
  case ND_PRE:
    (void)strcpy(member, ".pre");
    break;
  case ND_SUC:
    (void)strcpy(member, ".suc");
    break;
  };
  (void)sprintf(spec, "%s(%s) -%s--%s%s-", df->df_link, 
            dicname ? dicname : member, nickname,
            (dm->dm_flags & DM_READOK) ? "r" : "",
            (dm->dm_flags & DM_WRITEOK) ? "w" : "");
  new_spec = malloc(strlen(spec) + 3); /* 3 for \r\n\0 */
  if (!new_spec) {
    goto return_ret;
  }
  strcpy(new_spec, spec);
  if (!(new_nick = allocStr((char *)nickname))) {
    (void)free(new_spec);
    goto return_ret;
  };
  free(ddt->ddt_spec);
  ddt->ddt_spec = new_spec;
  free(dm->dm_nickname);
  dm->dm_nickname = new_nick;
  ret = 0;

 return_ret:
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(spec);
#endif
  return ret;
}

int
DMchmod(dm, mode)
struct DM *dm;
int mode;
{
  struct DF *df = dm->dm_file;
  struct DDT      *ddt = dm->dm_line;
  char            *new_spec;
  unsigned newflags = dm->dm_flags;
  int ret = -1;
#ifndef USE_MALLOC_FOR_BIG_ARRAY
  char            spec[RK_LINE_BMAX];
#else
  char *spec = malloc(RK_LINE_BMAX);
  if (!spec) {
    return ret;
  }
#endif

  if (!df || !df->df_link || !ddt || !ddt->ddt_spec)
    goto return_ret;

  /* READ パーミッションの操作 */
  if ((mode & (RK_ENABLE_READ | RK_DISABLE_READ)) == RK_ENABLE_READ) {
    newflags |= DM_READOK;
  }
  else if ((mode & (RK_ENABLE_READ | RK_DISABLE_READ)) == RK_DISABLE_READ) {
    newflags &= ~DM_READOK;
  }

  /* WRITE パーミッションの操作 */
  if ((mode & (RK_ENABLE_WRITE | RK_DISABLE_WRITE)) == RK_ENABLE_WRITE) {
    newflags |= DM_WRITEOK;
  }
  else if ((mode & (RK_ENABLE_WRITE | RK_DISABLE_WRITE)) == RK_DISABLE_WRITE) {
    newflags &= ~DM_WRITEOK;
  }

  if (newflags != dm->dm_flags) {
    if (df->df_direct->dd_flags & DD_WRITEOK) {
      dm->dm_flags = newflags;
      (void)sprintf(spec, "%s(%s) -%s--%s%s-",
                df->df_link, dm->dm_dicname, dm->dm_nickname,
                (dm->dm_flags & DM_READOK) ? "r" : "",
                (dm->dm_flags & DM_WRITEOK) ? "w" : "");
      new_spec = malloc(strlen(spec) + 3); /* 3 for \r\n\0 */
      if (!new_spec) {
      ret = NOTALC;
      goto return_ret;
      }
      strcpy(new_spec, spec);
      free(ddt->ddt_spec);
      ddt->ddt_spec = new_spec;
    }
  }
  ret = (((dm->dm_flags & DM_WRITEOK) ? RK_ENABLE_WRITE : RK_DISABLE_WRITE) |
       ((dm->dm_flags & DM_READOK) ? RK_ENABLE_READ : RK_DISABLE_READ));

 return_ret:
#ifdef USE_MALLOC_FOR_BIG_ARRAY
  (void)free(spec);
#endif
  return ret;
}

int
DDchmod(dd, mode)
struct DD *dd;
int mode;
{
  char *dicsdir;
  unsigned newflags = dd->dd_flags;

  /* READ パーミッションの操作 */
  if ((mode & (RK_ENABLE_READ | RK_DISABLE_READ)) == RK_ENABLE_READ) {
    newflags |= DD_READOK;
  }
  else if ((mode & (RK_ENABLE_READ | RK_DISABLE_READ)) == RK_DISABLE_READ) {
    newflags &= ~DD_READOK;
  }

  /* WRITE パーミッションの操作 */
  if ((mode & (RK_ENABLE_WRITE | RK_DISABLE_WRITE)) == RK_ENABLE_WRITE) {
    newflags |= DD_WRITEOK;
  }
  else if ((mode & (RK_ENABLE_WRITE | RK_DISABLE_WRITE)) == RK_DISABLE_WRITE) {
    newflags &= ~DD_WRITEOK;
  }

  if (newflags != dd->dd_flags) {
    dicsdir = malloc(strlen(dd->dd_path) + strlen("/dics.dir") + 1);
    if (dicsdir) {
      int filemode;

      strcpy(dicsdir, dd->dd_path);
      strcat(dicsdir, "/dics.dir");

      filemode = ((newflags & DD_WRITEOK) ? 0640 : 0440)
      | ((newflags & DD_READOK) ? 04 : 0);

      if (chmod(dicsdir, filemode) == 0) {
      dd->dd_flags = newflags;
      }
      free((char *)dicsdir);
    }
  }
  newflags = dd->dd_flags;
  return (((newflags & DD_WRITEOK) ? RK_ENABLE_WRITE : RK_DISABLE_WRITE) |
        ((newflags & DD_READOK) ? RK_ENABLE_READ : RK_DISABLE_READ));
}

int
_RkMountMD(cx, dm, qm, mode, firsttime)
     struct RkContext   *cx;
     struct DM          *dm;
     struct DM          *qm;
     int          mode;
     int          firsttime;
{
  struct MD *md, *head;
  struct DF *df;
  struct DD *dd;
  char            *file;
  int       status;

  if (!dm || !(md = (struct MD *)Calloc(1, sizeof(struct MD))))
    return -1;
  /* increment the reference counter */
  if (dm->dm_rcount == 0) {
    df = dm->dm_file;
    dd = df->df_direct;
    if (!(file = _RkCreatePath(dd, df->df_link))) {
      (void)free((char *)md);
      return -1;
    };
    status = DST_OPEN(dm, file,  DM_WRITABLE, cx->gram->gramdic);
    (void)free(file);
    if (status) {
      (void)free((char *)md);
      return -1;
    };
  };
  if (qm && qm->dm_rcount == 0) {
    df = qm->dm_file;
    dd = df->df_direct;
    if (!(file = _RkCreatePath(dd, df->df_link))) {
      (void)free((char *)md);
      return -1;
    };
    status = FQopen(dm, qm, file, DM_WRITABLE);
    (void)free(file);
    if (status) {
      (void)free((char *)md);
      return -1;
    };
  };
  /* use the dic as the default grammatical dic if it contains */
  if (firsttime && DM2TYPE(dm) == DF_PERMDIC && dm->dm_gram) {
    cx->gram = dm->dm_gram;
    cx->gram->refcount++;
  }
  /* increment the reference counter */
  dm->dm_rcount++;
  if (qm) {
    qm->dm_rcount++;
    if (!cx->nv && qm->dm_nv)
      cx->nv = qm->dm_nv;
  }
  /* put it at the end of the mount list */
  head = cx->md[dm->dm_class];
  md->md_next = head;
  md->md_prev = head->md_prev;
  head->md_prev = md;
  md->md_prev->md_next = md;
  md->md_dic = dm;
  md->md_freq = qm;
  md->md_flags = mode&MD_WRITE;
  /* wait for the translation to finish */
  if (IS_XFERCTX(cx)) 
    md->md_flags |= MD_MPEND;
  return 0;
}

void
_RkUmountMD(cx, md)
     struct RkContext   *cx;
     struct MD          *md;
{
  struct DM *dm = md->md_dic;
  struct DM *qm = md->md_freq;
  struct DF *df;
  struct DD *dd;
  char            *file;
  
  cx->dmprev = (struct DM *)0;
  cx->qmprev = (struct DM *)0;
  if (IS_XFERCTX(cx))
    md->md_flags |= MD_UPEND;
  else {
    md->md_prev->md_next = md->md_next;
    md->md_next->md_prev = md->md_prev;
    (void)free((char *)md);
    if (qm) {
      df = qm->dm_file;
      dd = df->df_direct;
      if (cx->nv == qm->dm_nv)
      cx->nv = (struct NV *)0;
      if (qm->dm_rcount > 0 && --qm->dm_rcount == 0) {
      file = _RkCreatePath(dd, df->df_link);
      if (file) {
        FQclose(cx, dm, qm, file);
        if (!df->df_rcount) {
          if (dd->dd_rcount > 0 && --dd->dd_rcount == 0)
            _RkFreeDD(dd);
        };
        (void)free(file);
      };
      };
    };
    if (dm->dm_rcount > 0 && --dm->dm_rcount == 0) {
      df = dm->dm_file;
      dd = df->df_direct;
      file  = _RkCreatePath(dd, df->df_link);
      if (file) {
      (void)DST_CLOSE(dm, file, cx->gram->gramdic);
      if (df->df_rcount == 0) {
        if (dd->dd_rcount > 0 && --dd->dd_rcount == 0)
          _RkFreeDD(dd);
      };
      (void)free(file);
      };
    };
  };
}

Generated by  Doxygen 1.6.0   Back to index