#include "stralloc.h"
#include "ftpcopy.h"
#include "bailout.h"

stralloc *
canon(stralloc *l_dir) /* feed me with 0 terminated strings only */
{
  static stralloc c=STRALLOC_INIT;
  char *p,*w;
  if (!stralloc_ready(&c,l_dir->len+1)) oom();

  p=l_dir->s;
  w=c.s;
  while (*p) {	
    /* ^../any ->  ^any */
    if (p==l_dir->s && p[0]=='.' && p[1]=='.' &&  (p[2]=='/' || p[2]==0)) {	
      p+=3;
    } else if (p[0]=='/' || p==l_dir->s) {
      if (p[0]=='/') p++;
      if (p[0]=='/') continue;
      if (*p=='.' && p[1]=='.' && (p[2]=='/' || p[2]==0)) {	
	while (w!=c.s &&w[-1]!='/') 
	  w--;
	if (w!=c.s) w--;
	p+=2;
	continue;
      } else if ((l_dir->s[0]=='/'||w!=c.s) && (w==c.s || w[-1]!='/'))
	*w++='/';
    }
    *w++=*p++;
  }
  c.len=w-c.s;
  if (!stralloc_0(&c)) oom();
  return &c;
}

#ifdef TEST
#include <stdio.h>
#include <string.h>
#include <time.h>

#ifdef LONGTEST
static stralloc *
old_canon(stralloc *l_dir) /* feed me with 0 terminated strings only */
{
static stralloc c=STRALLOC_INIT;
char *p,*end,*w;
if (!stralloc_copy(&c,l_dir)) oom();
if (!stralloc_readyplus(&c,l_dir->len+1)) oom();
p=l_dir->s;
end=l_dir->s+l_dir->len;
w=c.s;

while (*p) {  
if (p[0]=='/' && p[1]=='.' && p[2]=='.' && (!p[3] || p[3]=='/')) {
while (w!=c.s && w[-1]!='/') w--;
*w='/';
p+=4;
} else if (p[0]=='/' && p[1]=='/')
p++;
else
*w++=*p++;
}
c.len=w-c.s;
if (!stralloc_0(&c)) oom();
return &c;
}

static stralloc *
gra_canon(stralloc *l_dir) /* feed me with 0 terminated strings only */
{
  static stralloc c=STRALLOC_INIT;
  char *p,*end,*w,*v;
  if (!stralloc_copy(&c,l_dir)) oom();
  if (!stralloc_readyplus(&c,l_dir->len+1)) oom();
  p=l_dir->s;
  end=l_dir->s+l_dir->len;
  w=c.s;

  while (*p) {  
    if (p[0]=='/' && p[1]=='.' && p[2]=='.' && (!p[3] || p[3]=='/')) {
      v=w;                                                                     
      while (v!=c.s && v[-1]!='/') v--;                                        
      if (v+2==w && v[0]=='.' && v[1]=='.') {                                  
        *w++=*p++;                                                             
      } else {                                                                 
        w=v;                                                                   
        p+=3;                                                                  
       if (*p) p++;                                                            
      }                                                                        
    }                                                                          
    else if ((p==l_dir->s || p[-1]=='/') && p[0]=='.' && p[1]=='/')            
      p+=2;                                                                    
    else if (p[0]=='/' && p[1]=='/')        
      p++;
    else
    *w++=*p++;
  }
  c.len=w-c.s;
  if (!stralloc_0(&c)) oom();
  return &c;
}
#endif


int main(int argc, char **argv)
{
  char buf[1024];
  static stralloc sa;
  stralloc *sa2;
  while (fgets(buf,sizeof(buf),stdin)) {
    char *p;
    char *c=strchr(buf,'\n');
    int x;
    if (c) *c=0;
    if (!stralloc_copys(&sa,buf)) _exit(1);
    if (!stralloc_0(&sa)) _exit(1);
    printf("in : %s:\n",buf);
    sa2=canon(&sa);
    printf("out: %s:\n",sa2->s);
#ifdef LONGTEST
    sa2=old_canon(&sa);
    printf("old: %s:\n",sa2->s);
    sa2=gra_canon(&sa);
    printf("gra: %s:\n",sa2->s);
#endif
  }
}
#endif


syntax highlighted by Code2HTML, v. 0.9.1