delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/1999/05/09/09:45:35

Date: Sun, 9 May 1999 16:43:25 +0300 (IDT)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: "Markus F.X.J. Oberhumer" <markus DOT oberhumer AT jk DOT uni-linz DOT ac DOT at>
cc: djgpp-workers AT delorie DOT com, Michel AT smr DOT nl, DJ Delorie <dj AT delorie DOT com>
Subject: RE: v2.03: wrapping up
In-Reply-To: <XFMail.990504151958.markus.oberhumer@jk.uni-linz.ac.at>
Message-ID: <Pine.SUN.3.91.990509163720.22269A-100000@is>
MIME-Version: 1.0
Reply-To: djgpp-workers AT delorie DOT com
X-Mailing-List: djgpp-workers AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

On Tue, 4 May 1999, Markus F.X.J. Oberhumer wrote:

> I still think that /dev/env/DJDIR~c:/djgpp~/bin could work, but we
> should definitely do more testing before deciding on this.

Here are the diffs to the current library sources to implement this 
feature, including the diffs to the docs.  I'd appreciate if people would 
take a look and see if there's anything that I missed.  If somebody has 
time to actually apply the diffs and run some tests, that would be great.

I will check this in in a day or two, unless somebody reveals problems in 
this code (or in the feature itself).

Thanks to all those who participated in the discussion, and to Mark for 
suggesting the idea in the first place.

*** src/libc/dos/io/putpath.c~1	Thu Oct 29 10:24:44 1998
--- src/libc/dos/io/putpath.c	Sun May  9 15:31:04 1999
***************
*** 8,20 ****
  #include <string.h>
  #include <errno.h>
  
! void
  _put_path(const char *path)
  {
!   _put_path2(path, 0);
  }
  
! void
  _put_path2(const char *path, int offset)
  {
    int o = __tb+offset;
--- 8,20 ----
  #include <string.h>
  #include <errno.h>
  
! int
  _put_path(const char *path)
  {
!   return _put_path2(path, 0);
  }
  
! int
  _put_path2(const char *path, int offset)
  {
    int o = __tb+offset;
*************** _put_path2(const char *path, int offset)
*** 47,52 ****
--- 47,117 ----
        path = p + 6;
        space -= 2;
      }
+     else if (strncmp(p+5, "env", 3) == 0
+              && (p[8] == '/' || p[8] == '\\') && p[9])
+     {
+       /* /dev/env/FOO/bar: expand env var FOO and generate %FOO%/bar */
+       char *var_name, *d;
+       char *var_value;
+       int new_offset;
+       int use_default = 1;
+       int c;
+ 
+       p += 9;           /* point to the beginning of the variable name */
+       var_name = alloca(strlen (p) + 1);
+       for (d = var_name; *p && *p != '/' && *p != '\\'; *d++ = *p++)
+         if (*p == '~')
+         {
+           if (p[1] == '~')      /* two ~ in a row mean a literal ~ */
+             p++;
+           else
+             break;
+         }
+       *d = '\0';
+       var_value = getenv(d = var_name);
+       if (var_value && *var_value)
+       {
+         /* The value of the env var can include special constructs
+            like /dev/x/foo or even a reference to another env var, so
+            we need to recursively invoke ourselves.  */
+         new_offset = _put_path2(var_value, offset);
+         space -= new_offset - offset;
+         o += new_offset - offset;
+         use_default = 0;
+       }
+       if (*p == '~')    /* use or skip the default value if present */
+       {
+         for (++p; *p; p++)
+         {
+           if (*p == '~')
+           {
+             if (p[1] == '~')
+               p++;
+             else
+               break;
+           }
+           if (use_default)
+             *d++ = *p;
+         }
+         if (use_default)
+         {
+           *d = '\0';
+           /* The default value may use special constructs as well.  */
+           new_offset = _put_path2(var_name, offset);
+           space -= new_offset - offset;
+           o += new_offset - offset;
+         }
+       }
+       else
+         p--;
+ 
+       /* if the rest of path begins with a slash, remove the trailing
+          slash in the transfer buffer */
+       if ((p[1] == '/' || p[1] == '\\') && o-1 >= __tb+offset
+           && ((c = _farnspeekb(o-1)) == '/' || c == '\\'))
+         o--;
+       path = p + 1;
+     }
      else if (p[5])
        path = p + 5;
    }
*************** _put_path2(const char *path, int offset)
*** 72,75 ****
--- 137,141 ----
  
    /* null terminate it */
    _farnspokeb(o, 0);
+   return o - __tb;
  }
*** /dev/null	Sun May  9 15:40:24 1999
--- src/libc/dos/io/putpath.txh	Sun May  9 15:40:00 1999
***************
*** 0 ****
--- 1,150 ----
+ @node _put_path, io
+ 
+ @subheading Syntax
+ 
+ @example
+ #include <libc/dosio.h>
+ 
+ int _put_path(const char *path);
+ int _put_path2(const char *path, int offset);
+ @end example
+ 
+ @subheading Description
+ 
+ These functions are used internally by all low-level library functions
+ that need to pass file names to DOS.  @code{_put_path} copies its
+ argument @var{path} to the @dfn{transfer buffer}
+ (@pxref{_go32_info_block}) starting at the beginning of the transfer
+ buffer; @code{_put_path2} does the same except that it puts the file
+ name starting at @var{offset} bytes from the beginning of the transfer
+ buffer.
+ 
+ These functions are meant to be called by low-level library functions,
+ not by applications.  You should only call them if you know what you are
+ doing.  In particular, if you call any library function between a call
+ to @code{_put_path} or @code{_put_path2} and the call to a DOS function
+ that uses the file name, the file name in the transfer buffer could be
+ wiped out, corrupted or otherwise changed.  You @emph{have} been
+ warned!
+ 
+ Some constructs in file names are transformed while copying them, to
+ allow transparent support for nifty features.  Here's the list of these
+ transformations:
+ 
+ @itemize @bullet{}
+ @item Multiple forward slashes are collapsed into a single slash.
+ 
+ Unix treats multiple slashes as a single slash, so some ported programs
+ pass names like @file{c:/foo//bar} to library functions.  DOS functions
+ choke on such file names, so collapsing the slashes prevents these names
+ from failing.
+ 
+ @item Trailing slashes are removed, except for root directories.
+ 
+ Various DOS calls cannot cope with file names like @file{c:/foo/}; this
+ feature solves this problem.
+ 
+ @item Translation of Unix device names.
+ 
+ Unix @file{/dev/null} is mapped to DOS-standard @file{NUL}, and Unix
+ @file{/dev/tty} to DOS-standard @file{CON}.  This provides for
+ transparent support of these special devices, e.g. in Unix shell
+ scripts.
+ 
+ @item Translation of DOS device names.
+ 
+ Any file name which begins with @file{/dev/} or @file{@var{x:}/dev/}
+ (where @var{x:} is any valid DOS drive letter) has the @file{/dev/} or
+ @file{@var{x:}/dev/} prefix removed, and the rest is passed to DOS.
+ This is because some DOS functions don't recognize device names unless
+ they are devoid of the drive and directory specifications, and programs
+ could add a drive and a directory if they convert a name like
+ @file{/dev/con} to a fully-qualified path name.
+ 
+ @item @file{/dev/x/} is translated into @file{x:/}.
+ 
+ This allows to use Unix-style absolute path names that begin with a
+ slash, instead of DOS-style names with a drive letter.  Some Unix
+ programs and shell scripts fail for file names that include colons,
+ which are part of the drive letter specification; this feature allows to
+ work around such problems by using e.g. @file{/dev/c/} where @file{c:/}
+ would fail.
+ 
+ @item @file{/dev/env/@var{foo}/} is replaced by the value of the environment
+ variable @var{foo}.
+ 
+ (In other words, you can think of environment variables as if they were
+ sub-directories of a fictitious directory @file{/dev/env}.)
+ 
+ This allows to use environment variable names inside path names compiled
+ into programs, and have them transparently expanded at run time.  For
+ example, @file{/dev/env/DJDIR/include} will expand to the exact path
+ name of the DJGPP include directory, no matter where DJGPP is installed
+ on the machine where the program runs.  (The value of @code{DJDIR} is
+ computed by the DJGPP startup code and pushed into the environment of
+ every DJGPP program before @code{main} is called.)
+ 
+ Note that environment variables are case-sensitive, so
+ @file{/dev/env/foo} and @file{/dev/env/FOO} are @strong{not} the same.
+ DOS shells usually upcase the name of the environment variable if you
+ set it with the built-in command @samp{SET}, so if you type
+ e.g. @samp{SET foo=bar}, the shell defines a variable named @code{FOO}.
+ 
+ If the environment variable is undefined, it will expand into an empty
+ string.  The expansion is done recursively, so environment variables may
+ reference other environment variables using the same @file{/dev/env/}
+ notation.  For example, if the variable @code{HOME} is set to
+ @file{/dev/env/DJDIR/home}, and DJGPP is installed in
+ @file{c:/software/djgpp}, then @file{/dev/env/HOME/sources} will expand
+ to @file{c:/software/djgpp/home}.
+ 
+ It is possible to supply a default value, to be used if the variable is
+ not defined, or has an empty value.  To this end, put the default value
+ after the name of the variable and delimit it by @samp{~}, like in
+ @file{/dev/env/DJDIR~c:/djgpp~/include}.
+ 
+ If you need to include a literal character @samp{~} in either the
+ environment variable name or in the default value that replaces it, use
+ two @samp{~}s in a row.  For example, @file{/dev/env/FOO~~} will expand
+ to the value of the variable @code{FOO~}.  Likewise,
+ @file{/dev/env/FOO~~BAR~foo~~baz~} will expand to the value of the
+ variable @code{FOO~BAR} if it is defined and nonempty, and to
+ @file{foo~baz} otherwise.  Leading @samp{~} in the default value isn't
+ supported (it is interpreted as part of the preceding variable name).
+ 
+ The default value may also reference (other) environment variables, but
+ nested default values can get tricky.  For example,
+ @file{/dev/env/foo~/dev/env/bar~} will work, but
+ @file{/dev/env/foo~/dev/env/bar~baz~~} will @strong{not}.  To use nested
+ default values, you need to double the quoting of the @samp{~}
+ characters, like in @file{/dev/env/foo~/dev/env/bar~~baz~~~}.
+ @end itemize
+ 
+ @subheading Return Value
+ 
+ Both functions return the offset into the transfer buffer of the
+ terminating null character that ends the file name.
+ 
+ @portability !ansi, !posix
+ 
+ @subheading Example
+ 
+ These functions are meant to be called by low-level library functions,
+ not by applications.  You should only call them if you know what you are
+ doing.  In particular, if you call any library function between a call
+ to @code{_put_path} or @code{_put_path2} and the call to a DOS function
+ that uses the file name, the file name in the transfer buffer could be
+ wiped out, corrupted and otherwise changed.  You @emph{have} been
+ warned!
+ 
+ @example
+  __dpmi_regs r;
+ 
+  _put_path("/dev/c/djgpp/bin/");
+  r.x.ax = 0x4300;  /* get file attributes */
+  r.x.ds = __tb >> 4;
+  r.x.dx = __tb & 0x0f;
+  __dpmi_int(0x21, &r);
+ @end example
+ 
+ 
*** include/libc/dosio.h~0	Sat Aug 31 22:09:34 1996
--- include/libc/dosio.h	Wed May  5 17:38:30 1999
***************
*** 21,28 ****
  
  /* puts "path" in the transfer buffer, fixing
     unix-allowed multi-slashes */
! void _put_path(const char *_path);
! void _put_path2(const char *_path, int _offset);
  
  /* Convenience functions for setting up transfers */
  
--- 21,28 ----
  
  /* puts "path" in the transfer buffer, fixing
     unix-allowed multi-slashes */
! int _put_path(const char *_path);
! int _put_path2(const char *_path, int _offset);
  
  /* Convenience functions for setting up transfers */
  

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019