00001
00002
00003
00004
00005
00006
00007
00008
00009
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
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
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
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
00102
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
00135 if(s->s->len && !IS_ANY_SEP(LAST_PUSHED()))
00136 PUSH('/');
00137
00138 if (!len) return;
00139
00140 #ifdef CHAR_CURRENT
00141
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
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
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
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
00235 from++;
00236 continue;
00237 }
00238 }
00239 #endif
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