ftp.nice.ch/pub/next/developer/languages/c/djgpp-NS.s.tar.gz#/djgpp/go32/glob.c

This is glob.c in view mode; [Download] [Up]

#include <ctype.h>
#include <dir.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <io.h>
#ifdef __GO32__
#include <sys/farptr.h>
#else
#include <alloc.h>
#endif

#define extern
#include "glob.h"
#undef extern
int (*__glob_sense_expand_from_proxy)(int original_expand_wildcards) = 0;
static int expand_wildcards = 0;

static void parse_chars(void *ptr, int (*func)(void *ptr));

static int argv_max = 0;

static int
string_getc(void *ptr)
{
  int c = *(*(char **)ptr)++;
  return c;
}

static int
file_getc(void *ptr)
{
  return fgetc((FILE *)ptr);
}

static char *
get_proxy(int i)
{
  int len;
  char *rv;
  int seg = __glob_proxy_vals[1];
  int ofs = __glob_proxy_vals[2];
  int c;
#ifdef __GO32__
  _farsetsel(_go32_conventional_mem_selector());
  ofs = seg * 16 + _farnspeekw(seg*16+ofs+2*i);
  for (len=0; _farnspeekb(ofs+len); len++);
  rv = (char *)malloc(len+1);
  if (!rv)
  {
    fprintf(stderr, "Error: out of memory gathering arguments\n");
    exit(1);
  }
  for (len=0; (c = _farnspeekb(ofs+len)) != 0; len++)
    rv[len] = c;
  rv[len] = 0;
#else
  ofs = peek(seg, ofs+2*i);
  for (len=0; peekb(seg, ofs+len); len++);
  rv = (char *)malloc(len+1);
  if (!rv)
  {
    fprintf(stderr, "Error: out of memory gathering arguments\n");
    exit(1);
  }
  for (len=0; (c = peekb(seg, ofs+len)) != 0; len++)
    rv[len] = c;
  rv[len] = 0;
#endif
  return rv;
}

static void
stash_arg_at(char *arg, int slot, int dup)
{
  if (__glob_argv == 0)
    argv_max = 0;
  if (slot >= argv_max)
  {
    int newmax = (argv_max + 1)*2;
    if (__glob_argv)
      __glob_argv = (char **)realloc(__glob_argv, newmax * sizeof(char *));
    else
    {
      __glob_argv = (char **)malloc(newmax * sizeof(char *));
      __glob_argc = 0;
      argv_max = 0;
    }
    if (!__glob_argv)
    {
      fprintf(stderr, "Error: out of memory gathering arguments\n");
      exit(1);
    }
    while (argv_max < newmax)
      __glob_argv[argv_max++] = 0;
  }
  __glob_argv[slot] = arg ? (dup ? strdup(arg) : arg) : 0;
  if (arg && !__glob_argv[slot])
  {
    fprintf(stderr, "Error: out of memory gathering arguments\n");
    exit(1);
  }
  if (arg && (slot >= __glob_argc))
    __glob_argc = slot + 1;
}

static void
stash_arg(char *arg)
{
  stash_arg_at(arg, __glob_argc ? __glob_argc : 1, 1);
}

static void
free_args(void)
{
  int i;
  for (i=0; i<argv_max; i++)
    if (__glob_argv[i])
    {
      free(__glob_argv[i]);
      __glob_argv[i] = 0;
    }
  __glob_argc = 0;
}

#define SINGLE_QUOTE '\''
#define DOUBLE_QUOTE '"'

#define	EOS	'\0'

#define isslash(c) ((c) == '\\' || (c) == '/')

static char *
rangematch(char *pattern, char test)
{
  char c, c2;
  int negate, ok;

  if ((negate = (*pattern == '!')) != 0)
    ++pattern;

  /*
   * TO DO: quoting
   */

  for (ok = 0; (c = *pattern++) != ']';)
  {
    if (c == EOS)
      return(NULL);		/* illegal pattern */
    if (*pattern == '-' && (c2 = pattern[1]) != EOS && c2 != ']')
    {
      if (c <= test && test <= c2)
	ok = 1;
      else if (isalpha(test) && c <= (test^0x20) && (test^0x20) <= c2)
	ok = 1;
      pattern += 2;
    }
    else if (tolower(c) == tolower(test))
      ok = 1;
  }
  return(ok == negate ? NULL : pattern);
}

static int hasdot;

static int
fnmatch(char *pattern,
	char *string)
{
  register char c;
  char test, *rangematch();

  for (;;)
    switch (c = *pattern++)
    {
    case EOS:
      return(*string == EOS);
    case '?':
      if ((test = *string++) == EOS ||
	  isslash(test))
	return(0);
      break;
    case '*':
      c = *pattern;
      /* collapse multiple stars */
      while (c == '*')
	c = *++pattern;

      /* optimize for pattern with * at end or before / */
      if (c == EOS || (c == '.' && pattern[1] == EOS && !hasdot))
	return(!strchr(string, '/'));
      else if (isslash(c))
      {
	if ((string = strpbrk(string, "/\\")) == NULL)
	  return(0);
	break;
      }

      /* general case, use recursion */
      while ((test = *string) != EOS)
      {
	if (fnmatch(pattern, string))
	  return(1);
	if (isslash(test))
	  break;
	++string;
      }
      return(0);
    case '[':
      if ((test = *string++) == EOS ||
	  isslash(test))
	return(0);
      if ((pattern = rangematch(pattern, test)) == NULL)
	return(0);
      break;
    default:
      string++;
      if (tolower(c) != tolower(string[-1]))
	return(0);
      break;
    }
}



#define PATH_MAX 140

static int lowcase = 0;
static int mustexist = 0;

static void
wildcard1(char *buf, char *bp, char *fp)
{
  char *slpos = strpbrk(fp, "/\\"), slsave='-';
  int done, i;
  struct ffblk ff;
  char *wildchars;
  if (slpos)
  {
    slsave = *slpos;
    *slpos = 0;
  }
  for (i=0; fp[i]; i++)
  {
    if (islower(fp[i]))
      lowcase = 1;
    if (isupper(fp[i]))
      lowcase = 0;
  }
  wildchars =  strpbrk(fp, "*?[]");
  if (!expand_wildcards || wildchars==0)
  {
    strcpy(bp, fp);
    if (slpos)
    {
      int bpl = strlen(bp);
      bp[bpl++] = slsave;
      bp[bpl] = 0;
      wildcard1(buf, bp+bpl, slpos+1);
    }
    else
    {
      if (wildchars == 0 && mustexist)
      {
	if (access(buf, 0) == 0)
	  stash_arg(buf);
      }
      else
	stash_arg(buf);
    }
  }
  else
  {
    strcpy(bp, "*.*");
    done = findfirst(buf, &ff, FA_RDONLY|FA_DIREC|FA_ARCH);
    while (!done)
    {
      if (ff.ff_name[0] != '.' || fp[0] == '.')
      {
	if (lowcase)
	  strlwr(ff.ff_name);
	hasdot = strchr(ff.ff_name, '.')!=0;
	if (fnmatch(fp, ff.ff_name))
	{
	  strcpy(bp, ff.ff_name);
	  if (slpos)
	  {
	    int bpl = strlen(bp);
	    bp[bpl++] = slsave;
	    bp[bpl] = 0;
	    mustexist++;
	    wildcard1(buf, bp+bpl, slpos+1);
	    mustexist--;
	  }
	  else
	    stash_arg(buf);
	}
      }
      done = findnext(&ff);
    }
  }
  if (slpos)
    *slpos = slsave;
}

static int
argv_cmp(void *av, void *bv)
{
  register char *a = *(char **)av;
  register char *b = *(char **)bv;
  return strcmp(a, b);
}

static void
wildcard(char *arg)
{
  char buf[140];
  char *bp, *fp;
  int oarg;

  lowcase = 1;
  bp=buf;
  fp=arg;
  if (fp[1] == ':')
  {
    *bp++ = *fp++;
    *bp++ = *fp++;
  }
  if (*fp == '/' || *fp == '\\')
    *bp++ = *fp++;
  oarg = __glob_argc;
  if (oarg < 1) oarg = 1;
  wildcard1(buf, bp, fp);
  if (oarg >= __glob_argc)
    stash_arg(arg);
  else
    qsort(__glob_argv+oarg, __glob_argc - oarg,
	  sizeof(char *), argv_cmp);
}

static void
expand_arg(char *arg)
{
  if (arg[0] == '@')
  {
    FILE *f = fopen(arg+1, "r");
    if (f)
    {
      parse_chars(f, file_getc);
      fclose(f);
      return;
    }
  }
  else if (expand_wildcards && strspn("*?[]", arg))
    wildcard(arg);
  else
    stash_arg(arg);
}

static void
parse_chars(void *ptr, int (*func)(void *ptr))
{
  int quote = 0;
  int needs_expansion = 0;
  char argbuf[1000];
  char *start = argbuf;
  int pending_arg = 0;
  int done = 0;
  int unc = -2;

  while (!done)
  {
    int c = (unc==-2) ? func(ptr) : unc;
    unc = -2;
    if (c <= 0)
    {
      if (pending_arg)
      {
	*start = 0;
	if (needs_expansion)
	  expand_arg(argbuf);
	else
	  stash_arg(argbuf);
	pending_arg = 0;
	start = argbuf;
      }
      done = 1;
    }
    else if (quote == SINGLE_QUOTE)
    {
      if (c == SINGLE_QUOTE)
	quote = 0;
      else
	*start++ = c;
    }
    else if (quote == DOUBLE_QUOTE)
    {
      if (c == DOUBLE_QUOTE)
	quote = 0;
      else if (c == '\\')
      {
	unc = func(ptr);
	if (strchr("\\'\"", unc))
	{
	  *start++ = unc;
	  unc = -2;
	}
	else if (unc != '\n')
	{
	  *start++ = c;
	}
      }
      else
	*start++ = c;
    }
    else if (isspace(c))
    {
      if (pending_arg)
      {
	*start = 0;
	if (needs_expansion)
	  expand_arg(argbuf);
	else
	  stash_arg(argbuf);
	pending_arg = 0;
	start = argbuf;
      }
    }
    else
    {
      if (c == SINGLE_QUOTE || c == DOUBLE_QUOTE)
	quote = c;
      else if (c == '\\')
      {
	unc = func(ptr);
	if (unc == '\n')
	  unc = -2;
	else if (strchr("\\'\"", unc) || isspace(unc))
	{
	  *start++ = unc;
	  unc = -2;
	}
	else
	  *start++ = '\\';
      }
      else
      {
	if (strchr("*?[]", c) || (c == '@' && start == argbuf))
	  needs_expansion = 1;
	*start++ = c;
      }
      pending_arg = 1;
    }
  }
}

static int
getenvargs(void)
{
  int i, ac;
  char aname[10];
  char *a0 = getenv("_argc");
  if (!a0)
    return 1;
  ac = atoi(a0);
  for (i=0; i<ac; i++)
  {
    sprintf(aname, "_argv%d", i);
    if (i == 0)
      stash_arg_at(getenv(aname), 0, 1);
    else
      expand_arg(getenv(aname));
  }
  return 0;
}

void
__glob_args(char *cmdline, char *dos_argv0, int _expand_wildcards)
{
  expand_wildcards = _expand_wildcards;
  free_args();
  __glob_argc = 0;
  __glob_proxy_count = 0;

  if (getenvargs())
  {
    parse_chars(&cmdline, string_getc);

    if (__glob_argc > 4 && strcmp(__glob_argv[1], "!proxy") == 0)
    {
      int i;
      for (i=0; i+2 < __glob_argc; i++)
      {
	unsigned long pval = strtoul(__glob_argv[i+2], 0, 16);
	__glob_proxy_vals[i] = (unsigned) pval;
      }
      free_args();
      __glob_proxy_count = i;
      if (__glob_sense_expand_from_proxy)
	expand_wildcards = __glob_sense_expand_from_proxy(expand_wildcards);
      stash_arg_at(get_proxy(0), 0, 1);
      for (i=1; i<__glob_proxy_vals[0]; i++)
	expand_arg(get_proxy(i));
    }
    else
      stash_arg_at(dos_argv0, 0, 1);
  }

  stash_arg_at(0, __glob_argc, 0);
}

void
__glob_env(char *app_name)
{
  FILE *djgpp_env;
  char *djgpp_var = getenv("DJGPP");
  char *copy;

  if (djgpp_var)
  {
    djgpp_env = fopen(djgpp_var, "rt");
    if (djgpp_env)
    {
      char line[2000];
      char base[12], *bp, *a0p, *tb = (char *)line;
      int this_prog = 1;
      base[0] = '[';
      bp = app_name;
      for (a0p = bp; *a0p; a0p++)
	if (strchr("\\/:", *a0p))
	  bp = a0p+1;
      for (a0p=base+1; *bp && *bp != '.';)
	*a0p++ = tolower(*bp++);
      *a0p++ = ']';
      *a0p++ = 0;
      while (fgets(tb, 2000, djgpp_env))
      {
	tb[strlen(tb)-1] = 0;
	if (tb[0] == 0)
	  continue;
	if (tb[0] == '[')
	{
	  if (strcmp(tb, base) == 0)
	    this_prog = 1;
	  else
	    this_prog = 0;
	}
	else
	{
	  if (this_prog)
	  {
	    char *tb2 = tb+strlen(tb)+1;
	    char *sp=tb, *dp=tb2;
	    while (*sp != '=')
	      *dp++ = *sp++;
	    if (*tb2 == '+')	/* non-overriding */
	    {
	      *dp = 0;
	      tb2++;
	      if (getenv(tb2))
		continue;	/* while fread */
	    }
	    *dp++ = *sp++;	/* copy the '=' */
	    while (*sp)
	    {
	      if (*sp == '%')
	      {
		char *pp;
		if (sp[1] == '%')
		{
		  *dp++ = '%';
		  sp += 2;
		}
		else
		{
		  char ps, *e, *dirend;
		  int dirpart=0, apsemi=0;
		  int mapup=0, maplow=0, mapfs=0, mapbs=0;
		  while (strchr(":;/\\<>", sp[1]))
		  {
		    switch (sp[1])
		    {
		    case ':':  dirpart=1; break;
		    case ';':  apsemi=1;  break;
		    case '/':  mapfs=1;   break;
		    case '\\': mapbs=1;   break;
		    case '<':  mapup=1;   break;
		    case '>':  maplow=1;  break;
		    }
		    sp++;
		  }
		  for (pp=sp+1; *pp && *pp != '%'; pp++);
		  ps = *pp;
		  *pp = 0;
		  e = getenv(sp+1);
		  dirend = dp;
		  if (e)
		  {
		    while (*e)
		    {
		      char ec = *e++;
		      if (strchr("\\/:", ec))
			dirend=dp;
		      if (mapup) ec = toupper(ec);
		      if (maplow) ec = tolower(ec);
		      if (mapfs && ec == '\\') ec = '/';
		      if (mapbs && ec == '/') ec = '\\';
		      *dp++ = ec;
		    }
		  }
		  if (dirpart)
		    dp = dirend;
		  if (apsemi && e)
		    *dp++ = ';';
		  if (ps == 0)
		    break;
		  sp = pp+1;
		}
	      }
	      else
		*dp++ = *sp++;
	    }
	    *dp++ = 0;
	    copy = strdup(tb2);
	    if (!copy)
	    {
	      fprintf(stderr, "Error: out of memory gathering environment\n");
	      exit(1);
	    }
	    putenv(copy);
	  }
	}
      }
      fclose(djgpp_env);
    }
  }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.