office-gobmx/dmake/path.c
Vladimir Glazounov 41faa44b02 CWS-TOOLING: integrate CWS cmcfixes62
2009-09-22 21:19:24 +0200 cmc  r276365 : #i100000# that's the most plausible explanation, -D$(CVER) is needed by scp2 under windows
2009-09-19 16:10:36 +0200 cmc  r276303 : #i100000# revert this for no partically good reason
2009-09-18 14:16:47 +0200 cmc  r276279 : remove extra build depend
2009-09-18 08:56:15 +0200 cmc  r276265 : #i100000# rerun autoconf
2009-09-17 14:59:38 +0200 cmc  r276245 : CWS-TOOLING: rebase CWS cmcfixes62 to trunk@276192 (milestone: DEV300:m59)
2009-09-10 16:40:49 +0200 pl  r276041 : fix warning
2009-09-10 11:34:55 +0200 pl  r276026 : disable warning from system header
2009-09-09 19:30:45 +0200 pl  r276013 : use osl_getAsciiFunctionSymbol instead of strange cast
2009-09-09 19:25:32 +0200 pl  r276012 : add some casting hacks to make compile on solaris cc
2009-09-09 19:10:48 +0200 pl  r276009 : add missing Configure option for solaris sparce 32bit
2009-09-09 18:37:05 +0200 pl  r276008 : merge fix for #i104525# into moved code
2009-09-07 13:28:08 +0200 cmc  r275894 : CWS-TOOLING: rebase CWS cmcfixes62 to trunk@275801 (milestone: DEV300:m57)
2009-08-28 12:36:27 +0200 cmc  r275523 : CWS-TOOLING: rebase CWS cmcfixes62 to trunk@275331 (milestone: DEV300:m56)
2009-08-26 12:56:18 +0200 cmc  r275413 : #i104088# use the right headers in the right place
2009-08-25 17:07:50 +0200 cmc  r275372 : #i104500# make openssl build on linux that isn't x86 or x86_64
2009-08-25 13:08:48 +0200 cmc  r275347 : #i89237# pretty picswitch up
2009-08-25 10:58:09 +0200 cmc  r275342 : #i104489# remove last unused code in starmath
2009-08-25 10:23:33 +0200 cmc  r275338 : #i104088# clean up the define post-move
2009-08-24 13:46:57 +0200 cmc  r275310 : #i104088# 64bit odbc api changes
2009-08-24 13:42:52 +0200 cmc  r275309 : #i89237# unify linux platform mks under a generic parent
2009-08-24 13:19:52 +0200 cmc  r275307 : #i104455# remove unused code
2009-08-24 13:10:56 +0200 cmc  r275306 : #i104088# 64bit odbc api changes
2009-08-24 10:07:50 +0200 cmc  r275293 : #i104306# move recent-used to vcl
2009-08-24 09:32:08 +0200 cmc  r275291 : #i104306# move recent-used to vcl
2009-08-23 22:01:07 +0200 cmc  r275286 : #i104306# move recently-used to vcl
2009-08-22 15:25:25 +0200 cmc  r275285 : #i104088# 64bit odbc api changes
2009-08-21 17:52:40 +0200 cmc  r275268 : #i104306# move recently-used to vcl
2009-08-21 14:38:26 +0200 cmc  r275257 : #i104408 make these headers ready for c++0x
2009-08-21 14:20:19 +0200 cmc  r275251 : #i104406# avoid overlapping strcpy to avoid bustage on recent toolchains
2009-08-21 14:14:25 +0200 cmc  r275250 : #i104385# silence 64bit warnings
2009-10-01 09:16:17 +00:00

337 lines
8.1 KiB
C

/* RCS $Id: path.c,v 1.6 2008-03-05 18:29:34 kz Exp $
--
-- SYNOPSIS
-- Pathname manipulation code
--
-- DESCRIPTION
-- Pathname routines to handle building and pulling appart
-- pathnames.
--
-- AUTHOR
-- Dennis Vadura, dvadura@dmake.wticorp.com
--
-- WWW
-- http://dmake.wticorp.com/
--
-- COPYRIGHT
-- Copyright (c) 1996,1997 by WTI Corp. All rights reserved.
--
-- This program is NOT free software; you can redistribute it and/or
-- modify it under the terms of the Software License Agreement Provided
-- in the file <distribution-root>/readme/license.txt.
--
-- LOG
-- Use cvs log to obtain detailed change logs.
*/
#include "extern.h"
#if __CYGWIN__
#include <sys/cygwin.h>
#include <errno.h>
#endif
/*
** Return the suffix portion of a filename, assumed to begin with a `.'.
*/
PUBLIC char *
Get_suffix(name)
char *name;
{
char *suff;
if(name == NIL(char) || (suff = strrchr(name, '.')) == NIL(char))
suff = ".NULL";
return (suff);
}
PUBLIC char *
Basename(path)/*
================
Return pointer to the basename part of path. path itself remains
unchanged. */
char *path;
{
char *p;
char *q;
if( path && *(q = path) ) {
for(; *(p=DmStrPbrk(q, DirBrkStr)) != '\0'; q = p+1 );
if( !*q ) {
for( p=q-1; p != path; --p )
if( strchr( DirBrkStr, *p ) == NIL(char) ) return( p+1 );
return( strchr(DirBrkStr, *p)?path:(p+1) );
}
path = q;
}
return( path );
}
PUBLIC char *
Filedir(path)
char *path;
{
char *p;
char *q;
if( path && *(q = path) ) {
for(; *(p=DmStrPbrk(q,DirBrkStr)) != '\0'; q=p+1 );
if (q == path) return("");
for(p=q-1; p!=path; --p)
if( strchr(DirBrkStr,*p) == NIL(char) )
break;
p[1] = '\0';
}
return(path);
}
PUBLIC char *
Build_path(dir, name)/*
=======================
Return a path that is created by concatenating dir and name. A directory
separater is added between them if needed. If dir is empty name is stripped
of leading slashes (if there) and returned.
The returned path is also cleaned from unneeded './' and 'foo/../'
elements and also multiple consequtive '/' are removed.
Note, the returned path is built in a static buffer, if it is to be used
later strdup should be used on the result returned by Build_path to create
a copy. */
char *dir;
char *name;
{
static char *path = NIL(char);
static unsigned buflen = 0;
int plen = 0;
int dlen = 0;
int len;
DB_ENTER( "Build_path" );
if( dir != NIL(char) ) dlen = strlen( dir );
if( name != NIL(char) ) plen = strlen( name );
len = plen+dlen+1+1; /* Reserve space for extra path separator. */
if( len > buflen ) {
buflen = (len+16) & ~0xf; /* buf is always multiple of 16 */
if( path == NIL(char) )
path = MALLOC( buflen, char );
else
path = realloc( path, (unsigned) (buflen*sizeof(char)) );
}
*path = '\0';
if( dlen ) {
strcpy( path, dir );
if( *path && strchr(DirBrkStr, dir[dlen-1]) == NIL(char) )
strcat( path, DirSepStr );
}
if ( plen ) {
while ( *name && strchr(DirBrkStr,*name) != 0 ) name++;
strcat( path, name );
}
DB_PRINT( "path", ("dir: %s name: %s", dir, name ));
DB_PRINT( "path", ("joined to: %s", path ));
Clean_path( path );
DB_PRINT( "path", ("cleaned to: %s", path ));
DB_RETURN( path );
}
void
Clean_path(path)/*
==================
Clean the path from irregular directory separators (if more than one are
allowed), remove unneeded './' and 'foo/../' elements and also multiple
consequtive '/'.
The resulting string is shorter than the original, therefore this function
works on the original string. */
char *path;
{
register char *p;
register char *q;
char *tpath;
int hasdriveletter = 0;
int delentry;
size_t len;
DB_ENTER( "Clean_path" );
/* Skip the root part. */
tpath=path;
#ifdef HAVE_DRIVE_LETTERS
/* Change all occurences from DirBrkStr to *DirSepStr. This assumes
* that when HAVE_DRIVE_LETTERS is set the directory separator is
* either '\' or '/'. */
if (*DirSepStr == '/')
for( q = tpath; (q = strchr(q, '\\')) != NIL(char); )
*q = *DirSepStr;
else
for( q = tpath; (q = strchr(q, '/')) != NIL(char); )
*q = *DirSepStr;
/* The following dosn't trigger often because normalize_path() uses
* a cygwin function and bypasses Clean_path() if it encounters a path
* with a drive letter. */
if( *tpath && tpath[1] == ':' && isalpha(*tpath) ) {
hasdriveletter = 1;
tpath+=2;
if( *tpath != *DirSepStr )
Warning("Malformed DOS path %s", path);
}
#endif
/* Collapse > 2 ( > 1 if its an absolute DOS path ) into one slash.
* Keep // as it is reserved in posix. */
q = tpath;
for( ; *q == *DirSepStr ; ++q )
;
if( q - tpath > 2 - hasdriveletter ) {
strcpy(tpath+1, q);
}
/* Set tpath after leading slash / drive letter. */
for( ; *tpath == *DirSepStr ; ++tpath )
;
q = tpath;
while( *q ) {
char *t;
/* p is NULL or greater than q. */
p=strchr(q, *DirSepStr);
if( !p ) break;
/* Remove multiple consequtive DirSepStr. */
if( p[1] == *DirSepStr ) {
t = p++; /* t points to first, p to second DirStrSep. */
/* Move p after the second (or possible more) DirSepStr. */
do {
p++;
}
while( *p == *DirSepStr);
len = strlen(p)+1;
memmove(t+1,p,len);
continue;
}
/* Remove './'. If OOODMAKEMODE is set do this only if it is not at
* the start of the path. */
if ( p-q == 1 && *q == '.' && (q != path || !STOBOOL(OOoDmMode)) ) {
len = strlen(p+1)+1;
memmove(q,p+1,len);
q = tpath;
continue;
}
/* If two '/' are in path check/remove 'foo/../' elements. */
t=strchr(p+1, *DirSepStr);
if( !t ) break;
/* Collaps this only if foo is neither '.' nor '..'. */
switch( p-q ) {
case 2:
delentry = !((q[0] == '.') && (q[1] == '.'));
break;
case 1:
delentry = !(q[0] == '.');
break;
default:
delentry = TRUE;
break;
}
if ( delentry
&& (t-p-1 == 2 && strncmp(p+1,"..",2) == 0) ) {
/* Skip one (or possible more) DirSepStr. */
do {
t++;
}
while( *t == *DirSepStr);
/* q points to first letter of the current directory/file. */
len = strlen(t)+1;
memmove(q,t,len);
q = tpath;
}
else
q = p+1;
}
DB_PRINT( "path", ("Cleaned path: %s", path ));
DB_VOID_RETURN;
}
char *
normalize_path(path)/*
=======================
Normalize the given path unless it contains a $ indicating a dynamic
prerequisite.
Special case: For absolute DOSish paths under cygwin a cygwin API
function is used to normalize the path optherwise Clean_path() is used.
Note, the returned path is built in a static buffer, if it is to be used
later a copy should be created. */
char *path;
{
static char *cpath = NIL(char);
DB_ENTER( "normalize_path" );
if ( !cpath && ( (cpath = MALLOC( PATH_MAX, char)) == NIL(char) ) )
No_ram();
/* If there is a $ in the path this can either mean a '$' character in
* a target definition or a dynamic macro expression in a prerequisite
* list. As dynamic macro expression must not be normalized and is
* indistinguishable from a literal $ characters at this point we skip
* the normalization if a $ is found. */
if( strchr(path, '$') ) {
DB_RETURN( path );
}
#if __CYGWIN__
/* Use cygwin function to convert a DOS path to a POSIX path. */
if( *path && path[1] == ':' && isalpha(*path) ) {
int err = cygwin_conv_to_posix_path(path, cpath);
if (err)
Fatal( "error converting \"%s\" - %s\n",
path, strerror (errno));
if( path[2] != '/' && path[2] != '\\' )
Warning("Malformed DOS path %s converted to %s", path, cpath);
}
else
#endif
{
strcpy( cpath, path );
Clean_path( cpath );
}
DB_PRINT( "path", ("normalized: %s", cpath ));
DB_RETURN( cpath );
}