Logo Search packages:      
Sourcecode: cjk version File versions

emtexdir.c

/* emtexdir.c -- written by Eberhard Mattes, donated to the public domain */

#if defined (__EMX__)
#include <emx/syscalls.h>
#else
#include "emdir.h"
#endif
#if defined(DJGPP) || defined(GO32)
#include <unistd.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <io.h>
#include "emtexdir.h"

#define FALSE 0
#define TRUE  1

void (*emtex_dir_find_callback)(const char *name, int ok) = NULL;

static int setup_add (struct emtex_dir *dst, const char *path)
{
  char *p;

  if (dst->used >= dst->alloc)
    {
      dst->alloc += 8;
      dst->list = realloc (dst->list, dst->alloc * sizeof (*dst->list));
      if (dst->list == NULL)
      return (FALSE);
    }
  p = strdup (path);
  if (p == NULL)
    return (FALSE);
  dst->list[dst->used++] = p;
  return (TRUE);
}


static int setup_subdir (struct emtex_dir *dst, char *path, size_t add,
                   unsigned flags, int recurse)
{
  int ok, i, end, len;
#if defined (__EMX__)
  struct _find find;
#else
  struct ll_findbuffer find;
#endif

  i = dst->used;
  strcpy (path + add, "*.*");
#if defined (__EMX__)
  ok = __findfirst (path, 0x10, &find) == 0;
#else
  ok = ll_findfirst (path, 0x10, &find);
#endif
  while (ok)
    {
      if ((find.attr & 0x10)
        && !(strcmp (find.name, ".") == 0 || strcmp (find.name, "..") == 0))
      {
        len = strlen (find.name);
        memcpy (path + add, find.name, len);
        path[add+len] = '\\';
        path[add+len+1] = 0;
        if (!setup_add (dst, path))
          return (FALSE);
      }
#if defined (__EMX__)
      ok = __findnext (&find) == 0;
#else
      ok = ll_findnext (&find);
#endif
    }
  if (recurse)
    {
      end = dst->used;
      while (i < end)
      {
        strcpy (path, dst->list[i]);
        if (!setup_subdir (dst, path, strlen (path), flags, TRUE))
          return (FALSE);
        ++i;
      }
    }
  return (TRUE);
}


static int setup_dir (struct emtex_dir *dst, char *path,
                  const char *base_dir, size_t base_dir_len,
                  const char *sub_dir,
                  unsigned flags)
{
  size_t i, len;

  memcpy (path, base_dir, base_dir_len);
  i = base_dir_len;
  if ((flags & EDS_BANG) && sub_dir == NULL)
    {
      flags &= ~(EDS_ONESUBDIR|EDS_ALLSUBDIR);
      if (i >= 2 && path[i-1] == '!' && path[i-2] == '!')
      {
        flags |= EDS_ALLSUBDIR;
        i -= 2;
      }
      else if (i >= 1 && path[i-1] == '!')
      {
        flags |= EDS_ONESUBDIR;
        --i;
      }
    }
  if (sub_dir != NULL && *sub_dir != 0)
    {
      if (i != 0 && path[i-1] != ':' && path[i-1] != '/' && path[i-1] != '\\')
      path[i++] = '\\';
      len = strlen (sub_dir);
      memcpy (path+i, sub_dir, len);
      i += len;
    }
  if (path[i-1] != ':' && path[i-1] != '/' && path[i-1] != '\\')
    path[i++] = '\\';
  path[i] = 0;
  if (!setup_add (dst, path))
    return (FALSE);
  if (flags & EDS_ALLSUBDIR)
    return (setup_subdir (dst, path, i, flags, TRUE));
  else if (flags & EDS_ONESUBDIR)
    return (setup_subdir (dst, path, i, flags, FALSE));
  else
    return (TRUE);
}


/*static */int setup_list (struct emtex_dir *dst, char *path,
                   const char *list, unsigned flags)
{
  const char *end;
  size_t i;

  for (;;)
    {
      while (*list == ' ' || *list == '\t')
      ++list;
      if (*list == 0)
      return (TRUE);
      end = list;
      while (*end != 0 && *end != ';')
      ++end;
      i = end - list;
      while (i > 0 && (list[i-1] == ' ' || list[i-1] == '\t'))
      --i;
      if (i != 0 && !setup_dir (dst, path, list, i, NULL, flags))
      return (FALSE);
      if (*end == 0)
      return (TRUE);
      list = end + 1;
    }
}


int emtex_dir_setup (struct emtex_dir *ed, const char *env, const char *dir,
                 unsigned flags)
{
  const char *val;
  char path[260];

  ed->alloc = 0;
  ed->used = 0;
  ed->list = NULL;
  if (env != NULL && (val = getenv (env)) != NULL)
    return (setup_list (ed, path, val, flags));
  else if ((val = getenv ("EMTEXDIR")) != NULL)
    return (setup_dir (ed, path, val, strlen (val), dir, flags));
  else
    return (setup_dir (ed, path, "\\emtex", 6, dir, flags));
}


static void pretty (char *path, unsigned flags)
{
  char *p;

  if (flags & EDF_FSLASH)
    for (p = path; *p != 0; ++p)
      if (*p == '\\')
      *p = '/';
}


#define ADDCHAR(C) \
    if (dst_size < 1) return (EDT_TOOLONG); \
    *dst++ = (C); --dst_size

int emtex_dir_trunc (char *dst, size_t dst_size, const char *src,
                 unsigned flags, int method)
{
  int len, truncated, dot;

  if (src[0] != 0 && src[1] == ':')
    {
      ADDCHAR (src[0]);
      ADDCHAR (src[1]);
      src += 2;
    }

  truncated = FALSE; dot = FALSE; len = 0;
  for (;;)
    {
      switch (*src)
      {
      case 0:
        ADDCHAR (0);
        return (truncated ? EDT_CHANGED : EDT_UNCHANGED);

      case ':':
        return (EDT_INVALID);

      case '/':
      case '\\':
        ADDCHAR (*src);
        len = 0; dot = FALSE;
        break;

      case '.':
        if (dot)
          return (EDT_INVALID);
        ADDCHAR (*src);

        /* ".." is allowed -- don't return EDT_INVALID for the next
           dot. */

        if (!(len == 0 && src[1] == '.'
            && (src[2] == 0 || src[2] == '/' || src[2] == '\\')))
          {
            len = 0; dot = TRUE;
          }
        break;

      default:
        if (dot && len == 3)
          truncated = TRUE;
        else if (!dot && len == 8)
          {
            truncated = TRUE;
            if (method == 0)
            {
              dst[-3] = dst[-2];
              dst[-2] = dst[-1];
              dst[-1] = *src;
            }
          }
        else
          {
            ADDCHAR (*src);
            ++len;
          }
        break;
      }
      ++src;
    }
}


static int find2 (const char *name, unsigned flags)
{
  int ok;

  ok = (access (name, 4) == 0);
  if (flags & EDF_TRACE)
    emtex_dir_find_callback (name, ok);
  return (ok);
}


static int find1 (char *path, size_t path_size, const char *dir,
              const char *fname, unsigned flags)
{
  char buf[260];
  int method, rc;
  size_t len, tmp;

  len = 0;
  if (dir != NULL)
    {
      tmp = strlen (dir);
      if (tmp >= sizeof (buf))
      return (FALSE);
      memcpy (buf, dir, tmp);
      len = tmp;
    }
  tmp = strlen (fname);
  if (len + tmp >= sizeof (buf))
    return (FALSE);
  memcpy (buf + len, fname, tmp + 1);
  len += tmp;
#if 0 /* wkim */
/* disabled for Win95's long file name support  */
/* -- Wonkoo Kim (wkim+@pitt.edu), May 18, 1997 */
  if (_osmode == DOS_MODE)
    {
      rc = emtex_dir_trunc (path, path_size, buf, flags, EDT_5_PLUS_3);
      if ((rc == EDT_UNCHANGED || rc == EDT_CHANGED) && find2 (path, flags))
      {
        pretty (path, flags);
        return (TRUE);
      }
      rc = emtex_dir_trunc (path, path_size, buf, flags, EDT_8);
      if (rc == EDT_CHANGED && find2 (path, flags))
      {
        pretty (path, flags);
        return (TRUE);
      }
      return (FALSE);
    }
  else
#endif      /* wkim */
    {
      if (len < path_size && find2 (buf, flags))
      {
        memcpy (path, buf, len + 1);
        pretty (path, flags);
        return (TRUE);
      }
      for (method = 0; method < 2; ++method)
      {
        rc = emtex_dir_trunc (path, path_size, buf, flags, method);
        if (rc == EDT_CHANGED && find2 (path, flags))
          {
            pretty (path, flags);
            return (TRUE);
          }
      }
      return (FALSE);
    }
}


int emtex_dir_find (char *path, size_t path_size,
                const struct emtex_dir *ed,
                const char *fname, unsigned flags)
{
  int i, absp;
  const char *p;

  absp = FALSE;
  for (p = fname; *p != 0; ++p)
    if (*p == ':' || *p == '/' || *p == '\\')
      {
      absp = TRUE;
      break;
      }

  if (absp)
    return (find1 (path, path_size, NULL, fname, flags));

  if ((flags & EDF_CWD) && find1 (path, path_size, NULL, fname, flags))
    return (TRUE);

  for (i = 0; i < ed->used; ++i)
    if (find1 (path, path_size, ed->list[i], fname, flags))
      return (TRUE);
  return (FALSE);
}


#if defined (TEST)

#include <stdio.h>

int main (int argc, char *argv[])
{
  struct emtex_dir ed;
  int i;
  unsigned flags1, flags2;
  char path[260];

  if (argc != 6)
    {
      puts ("Usage: emtexdir <flags> <flags> <env> <dir> <fname>");
      return (1);
    }

  flags1 = (unsigned)strtol (argv[1], NULL, 0);
  flags2 = (unsigned)strtol (argv[2], NULL, 0);

  if (!emtex_dir_setup (&ed, argv[3], argv[4], flags1))
    {
      fputs ("emtex_dir_setup failed\n", stderr);
      return (2);
    }

  printf ("Directories:\n");
  for (i = 0; i < ed.used; ++i)
    printf ("  %s\n", ed.list[i]);

  if (!emtex_dir_find (path, sizeof (path), &ed, argv[5], flags2))
    puts ("File not found");
  else
    printf ("Path: %s\n", path);
  return (0);
}

#endif

Generated by  Doxygen 1.6.0   Back to index