
int
physfs_util_binrelative_add_to_searchpath(const char *newDir,
					  int appendToPath)
{
#define BATSP_STRSIZE 1000
  const char *const basedir = PHYSFS_getBaseDir();
  if (basedir && newDir) {
    char c;
    int ndpos = 0;
    int dpos = 0;
    const char *const sep = PHYSFS_getDirSeparator();
    int seplen = strlen(sep);
    char newname[BATSP_STRSIZE];
    int dotdotcount = 0;

    newname[BATSP_STRSIZE-1] = '\0'; /* a safeguard... */

    if ('/' == newDir[0]) {
      /* if newDir has been formulated like an absolute path then
	 leave it relative to the pwd rather than the basedir, but
	 still do the unix-directory-like munging. */
      ++ndpos;
    } else {
      strncpy(&newname[dpos], basedir, BATSP_STRSIZE-1);
      dpos += strlen(basedir);
    }

    do {
      c = newDir[ndpos];

      /* spot '../' or '..[END OF STRING]' */
      if (0 == dotdotcount) {
	if ('.' == c) {
	  ++dotdotcount;
	} else {
	  dotdotcount = 0;
	}
      } else if (1 == dotdotcount) {
	if ('.' == c) {
	  ++dotdotcount;
	} else {
	  dotdotcount = 0;
	}
      } else if (2 == dotdotcount) {
	if ('\0' == c || '/' == c) {
	  ++dotdotcount;
	} else {
	  dotdotcount = 0;
	}
      }

      /* if we saw a '..' in the newDir then strip two directory
	 levels off of newname (one to get rid of '..' and another to
	 get rid of the preceding path segment that it nullifies). */
      if (3 == dotdotcount) {
	int seen_seps = 0;
	/* iterate backwards past a dirseparator, until the character after
	   the dirseparator preceding that one. */
	--dpos;
	while (dpos >= (1 + seplen) &&
	       ! (1 == seen_seps &&
		  0 == strncmp(sep,&newname[dpos - seplen],seplen)) ) {
	  if (0 == strncmp(sep,&newname[dpos],seplen)) {
	    /* just passed a separator while iterating backwards */
	    ++seen_seps;
	  }
	  --dpos;
	}
	dotdotcount = 0;
      } else {
	/* we didn't see '..' (yet); copy path chararcter as usual. */
	if ('/' != c) {
	  if (dpos < BATSP_STRSIZE-1) {
	    newname[dpos] = c;
	    ++dpos;
	  }
	} else {
	  /* it's a path separator (treat multiple successive slashes
	     as one); put the system-dependant separator into newname. */
	  if (ndpos >= 1 && '/' != newDir[ndpos-1]) {
	    int i = 0;
	    while (sep[i] != '\0') {
	      if (dpos < BATSP_STRSIZE-1) {
		newname[dpos] = sep[i];
		++dpos;
	      }
	      ++i;
	    }
	  }
	}
      }

      ++ndpos;
    } while ('\0' != c);
    newname[dpos] = '\0'; /* be very confident that we've written
			     the string terminator... */
    /*ZLOG(VERBOSE, "adding '%s'", newname);*/
    return PHYSFS_addToSearchPath(newname, appendToPath);
  } else {
    return PHYSFS_addToSearchPath(newDir, appendToPath);
  }
#undef BATSP_STRSIZE
}
