2f8a602001-06-10Henrik Grubbström (Grubba) /*
dd10722001-09-24Fredrik Hübinette (Hubbe)  * $Id: combine_path.h,v 1.9 2001/09/25 03:13:23 hubbe Exp $
2f8a602001-06-10Henrik Grubbström (Grubba)  * * Combine path template. * */
8e06782001-06-07Fredrik Hübinette (Hubbe) #undef IS_SEP #undef IS_ABS #undef IS_ROOT #undef F_COMBINE_PATH #undef APPEND_PATH #define COMBINE_PATH_DEBUG 0 #ifdef UNIX_COMBINE_PATH #define IS_SEP(X) ( (X)=='/' ) #define IS_ABS(X) (IS_SEP( INDEX_PCHARP((X),0))?1:0) #define APPEND_PATH append_path_unix #define F_COMBINE_PATH f_combine_path_unix #endif /* UNIX_COMBINE_PATH */ #ifdef NT_COMBINE_PATH #define IS_SEP(X) ( (X) == '/' || (X) == '\\' ) static int find_absolute(PCHARP s) { int c0=INDEX_PCHARP(s,0); int c1=c0?INDEX_PCHARP(s,1):0; if(isalpha(c0) && c1==':' && IS_SEP(INDEX_PCHARP(s,2))) return 3; if(IS_SEP(c0) && IS_SEP(c1)) { int l;
dd10722001-09-24Fredrik Hübinette (Hubbe)  for(l=2;INDEX_PCHARP(s,l) && !IS_SEP(INDEX_PCHARP(s,l));l++);
8e06782001-06-07Fredrik Hübinette (Hubbe)  return l; } return 0; } #define IS_ABS(X) find_absolute((X)) #define IS_ROOT(X) ( IS_SEP( INDEX_PCHARP((X),0) )?1:0) #define APPEND_PATH append_path_nt #define F_COMBINE_PATH f_combine_path_nt #endif /* NT_COMBINE_PATH */ static void APPEND_PATH(struct string_builder *s, PCHARP path, size_t len) { size_t from=0;
1f88bf2001-09-24Henrik Grubbström (Grubba)  int tmp;
8e06782001-06-07Fredrik Hübinette (Hubbe)  int abs=0; /* First, check if path is absolute, * if so ignore anything already in 's' */ abs=IS_ABS(MKPCHARP_STR(s->s)); if((tmp=IS_ABS(path))) { s->s->len=0; s->known_shift=0; string_builder_append(s, path, tmp); from+=tmp; abs++; } #ifdef IS_ROOT else if((tmp=IS_ROOT(path))) { int tmp2; abs++; s->known_shift=0; if((tmp2=IS_ABS(MKPCHARP_STR(s->s)))) { s->s->len=tmp2; }else{ s->s->len=0; string_builder_append(s, path, tmp); } from+=tmp; } #endif #define LAST_PUSHED() (s->s->len ? index_shared_string(s->s,s->s->len-1) : 0) #define PUSH(X) string_builder_putchar(s,(X))
2f8a602001-06-10Henrik Grubbström (Grubba)  /* Ensure s ends with a separator. */
8e06782001-06-07Fredrik Hübinette (Hubbe)  if(s->s->len && !IS_SEP(LAST_PUSHED())) PUSH('/');
279f6a2001-06-11Henrik Grubbström (Grubba)  if (!len) return;
2f8a602001-06-10Henrik Grubbström (Grubba)  /* Remove initial "./" if any. */
913b262001-06-10Henrik Grubbström (Grubba)  if(s->s->len==2)
8e06782001-06-07Fredrik Hübinette (Hubbe)  { PCHARP to=MKPCHARP_STR(s->s); if(INDEX_PCHARP(to, 0) == '.') { s->s->len=0; s->known_shift=0; } } while(1) { #if COMBINE_PATH_DEBUG > 1 s->s->str[s->s->len]=0;
2f8a602001-06-10Henrik Grubbström (Grubba)  fprintf(stderr, "combine_path(2), TO: \"%s\"\n", s->s->str); fprintf(stderr, "combine_path(2), FROM (%d): \"%s\"\n", from, path.ptr+from);
8e06782001-06-07Fredrik Hübinette (Hubbe) #endif if(IS_SEP(LAST_PUSHED())) { while(s->s->len && IS_SEP(LAST_PUSHED())) s->s->len--; PUSH('/'); if(from<len && INDEX_PCHARP(path, from) == '.') { int c3; #if COMBINE_PATH_DEBUG > 0 s->s->str[s->s->len]=0;
2f8a602001-06-10Henrik Grubbström (Grubba)  fprintf(stderr, "combine_path(0), TO: \"%s\"\n", s->s->str); fprintf(stderr, "combine_path(0), FROM (%d): \"%s\"\n", from, path.ptr+from);
8e06782001-06-07Fredrik Hübinette (Hubbe) #endif switch(INDEX_PCHARP(path, from+1)) { case '.': c3=INDEX_PCHARP(path, from+2); if(IS_SEP(c3) || !c3) {
2f8a602001-06-10Henrik Grubbström (Grubba)  /* Handle "..". */
8e06782001-06-07Fredrik Hübinette (Hubbe)  int tmp=s->s->len-1;
2f8a602001-06-10Henrik Grubbström (Grubba)  if (tmp) { while(--tmp>=0) if(IS_SEP(index_shared_string(s->s, tmp))) break; tmp++; } else if (IS_SEP(index_shared_string(s->s, 0))) { tmp++; }
8e06782001-06-07Fredrik Hübinette (Hubbe) 
dbe48f2001-06-10Henrik Grubbström (Grubba)  if ((tmp+1 < s->s->len) &&
7ebc3e2001-06-10Henrik Grubbström (Grubba)  (index_shared_string(s->s,tmp)=='.') && (index_shared_string(s->s,tmp+1)=='.') &&
dbe48f2001-06-10Henrik Grubbström (Grubba)  ( (tmp+2 == s->s->len) ||
61fdf52001-06-10Henrik Grubbström (Grubba)  IS_SEP(index_shared_string(s->s,tmp+2))))
8e06782001-06-07Fredrik Hübinette (Hubbe)  break; from+=2; s->s->len=tmp; s->known_shift=0; #if COMBINE_PATH_DEBUG > 0 s->s->str[s->s->len]=0; fprintf(stderr,"combine_path(1), TO: %s\n",s->s->str); fprintf(stderr,"combine_path(1), FROM (%d): %s\n",from,path.ptr+from); #endif continue; } break; case 0: case '/': #ifdef NT_COMBINE_PATH case '\\': #endif
2f8a602001-06-10Henrik Grubbström (Grubba)  /* Handle ".". */ from++; continue;
8e06782001-06-07Fredrik Hübinette (Hubbe)  } } } if(from>=len) break; PUSH(INDEX_PCHARP(path, from++)); }
913b262001-06-10Henrik Grubbström (Grubba)  if((s->s->len > 1) &&
8e06782001-06-07Fredrik Hübinette (Hubbe)  !IS_SEP(INDEX_PCHARP(path, from-1)) && IS_SEP(LAST_PUSHED())) s->s->len--; if(!s->s->len) { if(abs) { PUSH('/'); }else{ PUSH('.'); } } } void F_COMBINE_PATH(INT32 args) { int e; int root=0; struct string_builder ret; ONERROR tmp; check_all_args("combine_path",args,BIT_STRING, BIT_STRING | BIT_MANY | BIT_VOID, 0); init_string_builder(&ret, 0); SET_ONERROR(tmp, free_string_builder, &ret); for(e=args-1;e>root;e--) { if(IS_ABS(MKPCHARP_STR(Pike_sp[e-args].u.string))) { root=e; break; } } APPEND_PATH(&ret, MKPCHARP_STR(Pike_sp[root-args].u.string), Pike_sp[root-args].u.string->len); root++; #ifdef IS_ROOT for(e=args-1;e>root;e--) { if(IS_ROOT(MKPCHARP_STR(Pike_sp[e-args].u.string))) { root=e; break; } } #endif while(root<args) { APPEND_PATH(&ret, MKPCHARP_STR(Pike_sp[root-args].u.string), Pike_sp[root-args].u.string->len); root++; } UNSET_ONERROR(tmp); pop_n_elems(args); push_string(finish_string_builder(&ret)); } #undef UNIX_COMBINE_PATH #undef NT_COMBINE_PATH