Main Page | Class List | Directories | File List | Class Members | File Members

combine_path.h

Go to the documentation of this file.
00001 /*
00002 || This file is part of Pike. For copyright information see COPYRIGHT.
00003 || Pike is distributed under GPL, LGPL and MPL. See the file COPYING
00004 || for more information.
00005 || $Id: combine_path.h,v 1.15 2004/05/01 15:25:04 mast Exp $
00006 */
00007 
00008 /*
00009  * Combine path template.
00010  *
00011  */
00012 
00013 #undef IS_SEP
00014 #undef IS_ANY_SEP
00015 #undef IS_ABS
00016 #undef IS_ROOT
00017 #undef COMBINE_PATH
00018 #undef APPEND_PATH
00019 #undef CHAR_CURRENT
00020 #undef CHAR_ROOT
00021 
00022 #define COMBINE_PATH_DEBUG 0
00023 
00024 #ifdef UNIX_COMBINE_PATH
00025 #define IS_SEP(X) ( (X)=='/' )
00026 #define IS_ABS(X) (IS_SEP( INDEX_PCHARP((X),0))?1:0)
00027 #define APPEND_PATH append_path_unix
00028 #define COMBINE_PATH combine_path_unix
00029 #define CHAR_CURRENT '.'
00030 #define CHAR_ROOT '/'
00031 #endif /* UNIX_COMBINE_PATH */
00032 
00033 
00034 
00035 #ifdef NT_COMBINE_PATH
00036 #define IS_SEP(X) ( (X) == '/' || (X) == '\\' )
00037 
00038 static int find_absolute(PCHARP s)
00039 {
00040   int c0=INDEX_PCHARP(s,0);
00041   int c1=c0?INDEX_PCHARP(s,1):0;
00042   if(isalpha(c0) && c1==':' && IS_SEP(INDEX_PCHARP(s,2)))
00043     return 3;
00044 
00045   if(IS_SEP(c0) && IS_SEP(c1))
00046   {
00047     int l;
00048     for(l=2;INDEX_PCHARP(s,l) && !IS_SEP(INDEX_PCHARP(s,l));l++);
00049     return INDEX_PCHARP(s,l)? l+1:l;
00050   }
00051 
00052   return 0;
00053 }
00054 #define IS_ABS(X) find_absolute((X))
00055 #define IS_ROOT(X) ( IS_SEP( INDEX_PCHARP((X),0) )?1:0)
00056 
00057 #define APPEND_PATH append_path_nt
00058 #define COMBINE_PATH combine_path_nt
00059 
00060 #define CHAR_CURRENT '.'
00061 #define CHAR_ROOT '/'
00062 
00063 #endif /* NT_COMBINE_PATH */
00064 
00065 
00066 #ifdef AMIGAOS_COMBINE_PATH
00067 #define IS_SEP(X) ( (X)=='/' )
00068 #define IS_ANY_SEP(X) ( (X) == '/' || (X) == ':' )
00069 #define IS_ABS(X) find_absolute2((X))
00070 #define IS_ROOT(X) ( ( INDEX_PCHARP((X),0) == CHAR_ROOT)?1:0)
00071 #define APPEND_PATH append_path_amigaos
00072 #define COMBINE_PATH combine_path_amigaos
00073 #define CHAR_ROOT ':'
00074 
00075 static int find_absolute2(PCHARP s)
00076 {
00077   int r=0, p=0;
00078   int c;
00079   while((c=INDEX_PCHARP(s,p))) {
00080     ++p;
00081     if(c == CHAR_ROOT)
00082       r = p;
00083   }
00084   return r>1? r:0;
00085 }
00086 
00087 #endif /* AMIGAOS_COMBINE_PATH */
00088 
00089 
00090 #ifndef IS_ANY_SEP
00091 #define IS_ANY_SEP(X) IS_SEP(X)
00092 #endif
00093 
00094 static void APPEND_PATH(struct string_builder *s,
00095                         PCHARP path,
00096                         size_t len)
00097 {
00098   size_t from=0;
00099   int tmp, abs;
00100 
00101   /* First, check if path is absolute, 
00102    * if so ignore anything already in 's'
00103    */
00104   abs=IS_ABS(MKPCHARP_STR(s->s));
00105   if((tmp=IS_ABS(path)))
00106   {
00107     s->s->len=0;
00108     s->known_shift=0;
00109     string_builder_append(s, path, tmp);
00110     from+=tmp;
00111     abs=tmp;
00112   }
00113 #ifdef IS_ROOT
00114   else if((tmp=IS_ROOT(path)))
00115   {
00116     int tmp2;
00117     s->known_shift=0;
00118     if((tmp2=IS_ABS(MKPCHARP_STR(s->s))))
00119     {
00120       s->s->len=tmp2;
00121       abs=tmp2;
00122     }else{
00123       s->s->len=0;
00124       string_builder_append(s, path, tmp);
00125       abs=tmp;
00126     }
00127     from+=tmp;
00128   }
00129 #endif
00130 
00131 #define LAST_PUSHED() (s->s->len ? index_shared_string(s->s,s->s->len-1) : 0)
00132 #define PUSH(X) string_builder_putchar(s,(X))
00133 
00134   /* Ensure s ends with a separator. */
00135   if(s->s->len && !IS_ANY_SEP(LAST_PUSHED()))
00136     PUSH('/');
00137 
00138   if (!len) return;
00139 
00140 #ifdef CHAR_CURRENT
00141   /* Remove initial "./" if any. */
00142   if(s->s->len==2)
00143   {
00144     PCHARP to=MKPCHARP_STR(s->s);
00145     if(INDEX_PCHARP(to, 0) == CHAR_CURRENT)
00146     {
00147       s->s->len=0;
00148       s->known_shift=0;
00149     }
00150   }
00151 #endif
00152 
00153   while(1)
00154   {
00155 #if COMBINE_PATH_DEBUG > 1
00156     s->s->str[s->s->len]=0;
00157     fprintf(stderr, "combine_path(2),   TO: \"%s\"\n", s->s->str);
00158     fprintf(stderr, "combine_path(2), FROM (%d): \"%s\"\n",
00159             from, path.ptr+from);
00160 #endif
00161     if(IS_SEP(LAST_PUSHED()))
00162     {
00163 #ifdef AMIGAOS_COMBINE_PATH
00164       if(from<len && INDEX_PCHARP(path, from) == '/' &&
00165          s->s->len>1 && !IS_ANY_SEP(index_shared_string(s->s,s->s->len-2))) {
00166         /* Handle "//" */
00167         int tmp=s->s->len-2;
00168         while(tmp>0 && !IS_ANY_SEP(index_shared_string(s->s,tmp-1)))
00169           --tmp;
00170         s->s->len=tmp;
00171         s->known_shift=0;
00172         from++;
00173         continue;
00174       }
00175 #else /* !AMIGAOS_COMBINE_PATH */
00176       while(s->s->len && IS_SEP(LAST_PUSHED()))
00177         s->s->len--;
00178       PUSH('/');
00179       if(from<len && INDEX_PCHARP(path, from) == '.')
00180       {
00181         int c3;
00182 #if COMBINE_PATH_DEBUG > 0
00183         s->s->str[s->s->len]=0;
00184         fprintf(stderr, "combine_path(0),   TO: \"%s\"\n", s->s->str);
00185         fprintf(stderr, "combine_path(0), FROM (%d): \"%s\"\n",
00186                 from, path.ptr+from);
00187 #endif
00188 
00189         switch(INDEX_PCHARP(path, from+1))
00190         {
00191           case '.':
00192             c3=INDEX_PCHARP(path, from+2);
00193             if(IS_SEP(c3) || !c3)
00194             {
00195               /* Handle "..". */
00196               int tmp=s->s->len-1;
00197               if (tmp) {
00198                 while(--tmp>=0)
00199                   if(IS_SEP(index_shared_string(s->s, tmp)))
00200                     break;
00201                 tmp++;
00202               } else if (IS_SEP(index_shared_string(s->s, 0))) {
00203                 tmp++;
00204               }
00205               
00206               if (tmp < abs)
00207                 tmp = abs;
00208               else
00209                 if ((tmp+1 < s->s->len) &&
00210                     (index_shared_string(s->s,tmp)=='.') &&
00211                     (index_shared_string(s->s,tmp+1)=='.') && 
00212                     ( (tmp+2 == s->s->len) ||
00213                       IS_SEP(index_shared_string(s->s,tmp+2))))
00214                   break;
00215 
00216               from+=(c3? 3:2);
00217               s->s->len=tmp;
00218               s->known_shift=0;
00219 
00220 #if COMBINE_PATH_DEBUG > 0
00221               s->s->str[s->s->len]=0;
00222               fprintf(stderr,"combine_path(1),   TO: %s\n",s->s->str);
00223               fprintf(stderr,"combine_path(1), FROM (%d): %s\n",from,path.ptr+from);
00224 #endif
00225               continue;
00226             }
00227             break;
00228             
00229           case 0:
00230           case '/':
00231 #ifdef NT_COMBINE_PATH
00232           case '\\':
00233 #endif
00234             /* Handle ".". */
00235             from++;
00236             continue;
00237         }
00238       }
00239 #endif /* !AMIGAOS_COMBINE_PATH */
00240     }
00241 
00242     if(from>=len) break;
00243     PUSH(INDEX_PCHARP(path, from++));
00244   }
00245   if((s->s->len > 1) && (s->s->len > abs) &&
00246      !IS_SEP(INDEX_PCHARP(path, from-1)) &&
00247      IS_SEP(LAST_PUSHED()))
00248     s->s->len--;
00249   
00250   if(!s->s->len)
00251   {
00252     if(abs)
00253     {
00254       PUSH(CHAR_ROOT);
00255 #ifdef CHAR_CURRENT
00256     }else{
00257       PUSH(CHAR_CURRENT);
00258       if(IS_SEP(INDEX_PCHARP(path, from-1)))
00259         PUSH('/');
00260 #endif
00261     }
00262   }
00263 }
00264 
00265 #define F_FUNC(X) PIKE_CONCAT(f_,X)
00266 
00267 void F_FUNC(COMBINE_PATH)(INT32 args)
00268 {
00269   int e;
00270   int root=0;
00271   struct string_builder ret;
00272   ONERROR tmp;
00273 
00274   check_all_args(DEFINETOSTR(COMBINE_PATH),args,
00275                  BIT_STRING, BIT_STRING | BIT_MANY | BIT_VOID, 0);
00276 
00277   init_string_builder(&ret, 0);
00278   SET_ONERROR(tmp, free_string_builder, &ret);
00279 
00280   for(e=args-1;e>root;e--)
00281   {
00282     if(IS_ABS(MKPCHARP_STR(Pike_sp[e-args].u.string)))
00283     {
00284       root=e;
00285       break;
00286     }
00287   }
00288 
00289   APPEND_PATH(&ret,
00290               MKPCHARP_STR(Pike_sp[root-args].u.string),
00291               Pike_sp[root-args].u.string->len);
00292   root++;
00293 
00294 #ifdef IS_ROOT
00295   for(e=args-1;e>root;e--)
00296   {
00297     if(IS_ROOT(MKPCHARP_STR(Pike_sp[e-args].u.string)))
00298     {
00299       root=e;
00300       break;
00301     }
00302   }
00303 #endif
00304   
00305   while(root<args)
00306   {
00307     APPEND_PATH(&ret,
00308                 MKPCHARP_STR(Pike_sp[root-args].u.string),
00309                 Pike_sp[root-args].u.string->len);
00310     root++;
00311   }
00312   UNSET_ONERROR(tmp);
00313   pop_n_elems(args);
00314   push_string(finish_string_builder(&ret));
00315 }
00316 
00317 
00318 
00319 #undef UNIX_COMBINE_PATH
00320 #undef NT_COMBINE_PATH
00321 #undef AMIGAOS_COMBINE_PATH

Generated on Fri Jul 22 23:44:24 2005 for Pike by  doxygen 1.3.9.1