.namespace [ 'File::Spec::Win32' ]

=head2 Description

=cut

.sub '__onload' :load
    load_bytecode 'File/Spec/Unix.pir'
    load_bytecode 'PGE.pbc'

    .local pmc self
    subclass self, 'File::Spec::Unix', 'File::Spec::Win32'

    .local pmc tmpdir
    tmpdir= new 'ResizableStringArray'

    set_global '_tmpdir', tmpdir
.end


.sub 'devnull' :method
    .return( 'nul' )
.end


.sub 'tmpdir' :method
    .local pmc tmpdir
    tmpdir= new 'ResizableStringArray'

    tmpdir= get_global '_tmpdir'

    .local int size
    size= tmpdir

    if size, return_cached

    .local pmc env
    env= new 'Env'

    .local string env_val

find_tmpdir:
    env_val= env['TMPDIR']
    if env_val, found_tmpdir
    goto find_temp

found_tmpdir:
    push tmpdir, env_val
    env_val= ''

find_temp:
    env_val= env['TEMP']
    if env_val, found_temp
    goto find_tmp

found_temp:
    push tmpdir, env_val
    env_val= ''

find_tmp:
    env_val= env['TMP']
    if env_val, found_tmp
    goto add_more

found_tmp:
    push tmpdir, env_val
    env_val= ''

add_more:
    push tmpdir, 'SYS:/temp'
    push tmpdir, 'C:/temp'
    push tmpdir, '/tmp'
    push tmpdir, '/'

store:
    set_global '_tmpdir', tmpdir
return_cached:
    .return( tmpdir )
.end


.sub case_tolerant :method
    .return( 1 )
.end


.sub 'file_name_is_absolute' :method
    .param string file

    .local pmc p6rule
    .local pmc rulesub
    .local pmc match

    p6rule= compreg 'PGE::Perl6Regex'

    ## m{^([a-z]:)?[\\/]}is
    rulesub= p6rule( ':ignorecase ^ ( <?alpha> \: )? <[\\/]>' )
    match= rulesub( file )

    .tailcall match.'__get_bool'()
.end


.sub 'catfile' :method
    _E_not_yet_implemented()

=for later development

    .param pmc args :slurpy
    .local pmc dir
    .local pmc file

    $I0= args
    unless $I0, return

    $P1= pop args
    file= new 'String'
    file= $P1

    file= self.'canonpath'( file )

    $I0= args
    unless $I0, return_file

    dir= self.'catdir'( args :flat )

    .local pmc p6rule
    .local pmc rulesub
    .local pmc match

    p6rule= compreg 'PGE::Perl6Regex'

    ## dir =~ m{\\$}is
    rulesub= p6rule( '\\ $' )
    match= rulesub( dir )

    if match, return_dir_file
    dir .= "\\"

return_dir_file:
    dir .= file
    .return( dir )
return_file:
    .return( file )
return:

=cut

.end


.sub 'catdir' :method
    .param pmc dirs :slurpy

    .local int num_args
    num_args= dirs

    unless num_args, return

    .local pmc p6rule, rulesub, match
    p6rule= compreg 'PGE::Perl6Regex'

    .local pmc dir
    dir= new 'String'
    .local int i
    i= 0

loop_dirs:
    if num_args <= i goto join_dirs
    dir= dirs[i]

    .local string s_dir, slash, bslash
    s_dir= dir
    slash= '/'
    bslash= '\'

loop_rule:
    $I0= index s_dir, slash
    if -1 == $I0 goto final_slash
    $I1= $I0 + 1
    $S2= substr s_dir, $I1
    substr s_dir, $I0, $I1, bslash
    concat s_dir, $S2
    goto loop_rule

final_slash:
    ## $_ .= "\\" unless m{\\$};
    $S0= substr s_dir, -1
    eq bslash, $S0, next_arg
    concat s_dir, bslash

    dir= s_dir
    dirs[i]= dir

next_arg:
    i += 1
    goto loop_dirs

join_dirs:
    ## return $self->canonpath(join('', @args));
    s_dir= join '', dirs
    dir= s_dir
    dir= self.'canonpath'( dir )
    .return( dir )
return:
.end


.sub 'path' :method
##TODO
    '_E_not_yet_implemented'()
.end


.sub 'canonpath' :method
    .param string path

    .local pmc p6rule, rulesub, match
    p6rule= compreg 'PGE::Perl6Regex'

match_1:
    ## $path =~ s/^([a-z]:)/\u$1/s;
    rulesub= p6rule( '^ ( <?[a..z]> \: )' )
do_match_1:
    match= rulesub( path )
    unless match, no_match_1
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= $P0
    $S0= upcase $S0
    substr path, $I0, $I1, $S0
no_match_1:

match_2:
    ## $path =~ s|/|\\|g;
    rulesub= p6rule( "/" )
do_match_2:
    match= rulesub( path )
    unless match, no_match_2
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= "\\"
    substr path, $I0, $I1, $S0
    goto do_match_2
no_match_2:

match_3:
    ## $path =~ s|([^\\])\\+|$1\\|g;
        ## xx\\\\xx  -> xx\xx
    rulesub= p6rule( '( <-[\\]> ) \+' )
do_match_3:
    match= rulesub( path )
    unless match, no_match_3
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= $P0
    $S0 .= "\\"
    substr path, $I0, $I1, $S0
    goto do_match_3
no_match_3:

match_4:
    ## $path =~ s|(\\\.)+\\|\\|g;
    ## xx\.\.\xx -> xx\xx
    rulesub= p6rule( '( \\ \. )+ \\' )
do_match_4:
    match= rulesub( path )
    unless match, no_match_4
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= "\\"
    substr path, $I0, $I1, $S0
    goto do_match_4
no_match_4:

match_5:
    ## $path =~ s|^(\.\\)+||s unless $path eq ".\\";
    ## .\xx      -> xx
    .local string relpath
    relpath= ".\\"

    iseq $I0, relpath, path
    if $I0, no_match_5
    rulesub= p6rule( '^ ( \. \\ )+ \\' )
do_match_5:
    match= rulesub( path )
    unless match, no_match_5
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= ""
    substr path, $I0, $I1, $S0
no_match_5:

match_6:
    ## $path =~ s|\\\Z(?!\n)||
    ##     unless $path =~ m{^([A-Z]:)?\\\Z(?!\n)}s;
    ## xx\       -> xx
    ## xx1/xx2/xx3/../../xx -> xx1/xx
    rulesub= p6rule( '$$ <!before \n>' )
    match= rulesub( path )
    if match, no_match_6

    rulesub= p6rule( '\\ \n? $' )
    match= rulesub( path )
    unless match, no_match_3
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= ""
    substr path, $I0, $I1, $S0
no_match_6:

match_7:
    ## $path =~ s|\\\.\.\.\\|\\\.\.\\\.\.\\|g;
    ## \...\ is 2 levels up
    rulesub= p6rule( '\\ \. \. \. \\' )
do_match_7:
    match= rulesub( path )
    unless match, no_match_7
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= "\\\.\.\\\.\.\\"
    substr path, $I0, $I1, $S0
    goto do_match_7
no_match_7:

match_8:
    ## $path =~ s|^\.\.\.\\|\.\.\\\.\.\\|g;
    ## ...\ is 2 levels up
    rulesub= p6rule( '^ \. \. \. \\' )
    match= rulesub( path )
do_match_8:
    unless match, no_match_8
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= "\.\.\\\.\.\\"
    substr path, $I0, $I1, $S0
    goto do_match_8
no_match_8:

match_9:
    ## return $path if $path =~ m|^\.\.|;
    ## skip relative paths
    rulesub= p6rule( '^ \. \.' )
    match= rulesub( path )
do_match_9:
    if match, return
no_match_9:

match_10:
    ## return $path unless $path =~ /\.\./;
    ## too few .'s to cleanup
    rulesub= p6rule( '\. \.' )
    match= rulesub( path )
do_match_10:
    unless match, return
no_match_10:

match_11:
    ## return $path if $path =~ /\.\.\.\./;
    ## too many .'s to cleanup
    rulesub= p6rule( '\. \. \. \.' )
    match= rulesub( path )
do_match_11:
    if match, return
no_match_11:

match_12:
    ## $path =~ s{^\\\.\.$}{\\};
    ## \..    -> \
    rulesub= p6rule( '^ \\ \. \. $' )
do_match_12:
    match= rulesub( path )
    unless match, no_match_12
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= "\\"
    substr path, $I0, $I1, $S0
no_match_12:

match_13:
    ## 1 while $path =~ s{^\\\.\.}{};
    ## \..\xx -> \xx
    rulesub= p6rule( '^ \\ \. \.' )
do_match_13:
    match= rulesub( path )
    unless match, no_match_13
    $P0= match[0]
    $I0= $P0.'from'()
    $I1= $P0.'to'()
    $S0= ""
    substr path, $I0, $I1, $S0
    goto match_13
no_match_13:

#    my ($vol,$s_dirs,$file) = $self->splitpath($path);
    .local string vol, s_dirs, file
    ( vol, s_dirs, file )= self.'splitpath'( path )

#    my @dirs = $self->splitdir($dirs);
    .local pmc a_dirs
    a_dirs= new 'ResizableStringArray'
    ( a_dirs )= self.'splitdir'( s_dirs )

## TODO unfinished
#    my (@base_dirs, @path_dirs);
#    my $dest = \@base_dirs;
#    for my $dir (@dirs){
#   $dest = \@path_dirs if $dir eq $self->updir;
#   push @$dest, $dir;
#    }
#    # for each .. in @path_dirs pop one item from
#    # @base_dirs
#    while (my $dir = shift @path_dirs){
#   unless ($dir eq $self->updir){
#       unshift @path_dirs, $dir;
#       last;
#   }
#   pop @base_dirs;
#    }
#    $path = $self->catpath(
#              $vol,
#              $self->catdir(@base_dirs, @path_dirs),
#              $file
#             );

return:
    .return( path )
.end


## TODO probably broken
.sub 'splitpath' :method
    .param string path
    .param int no_file
    .local string volume, directory, file

    '_E_not_yet_implemented'()
    volume= ''
    directory= ''
    file= ''

    .local pmc p6rule
    .local pmc rulesub
    .local pmc match

    p6rule= compreg 'PGE::Perl6Regex'

    unless no_file, with_file
    ## m{^( (?:[a-zA-Z]:|(?:\\\\|//)[^\\/]+[\\/][^\\/]+)? )
    ##       (.*)
    ##  }xs;

## TODO these are funky and might not be right
    rulesub= p6rule( ' ^ ( <[a..zA..Z]> \: | [\\ | //] <-[\\/]>+ <[\\/]> <-[\\/]>+ )?  (.*) ' )
    match= rulesub( path )
    unless match, return
    $P0= match[0]
    $S0= $P0
    volume= $S0

    $P0= match[1]
    $S0= $P0
    directory= $P0
    goto return

with_file:
## TODO these are funky and might not be right
    rulesub= p6rule( ' ^ ( < [a..zA..Z] \: | <\\ \\ | //> [^\\/]+ [\\/] [^\\/]+ >)?  ( < .* [\\/] < \. \.? <\n? $$>? >?) (.*) ' )
    match= rulesub( path )
    unless match, return

    $P0= match[0]
    $S0= $P0
    volume= $S0

    $P0= match[1]
    $S0= $P0
    directory= $P0

    $P0= match[2]
    $S0= $P0
    file= $P0

return:
    .return( volume, directory, file )
.end


## TODO unfinished
.sub 'splitdir' :method
    .param string directories
    '_E_not_yet_implemented'()

    .local string dir_copy
    dir_copy= directories

    .local pmc a_directories
    a_directories= new 'ResizableStringArray'

    .local pmc p6rule
    .local pmc rulesub
    .local pmc match

    p6rule= compreg 'PGE::Perl6Regex'

## TODO this whole rule section
    rulesub= p6rule( '^ <[\\/]>? ( <-[\\/]>? ) <[\\/]>? ' )
match_1:
    match= rulesub( dir_copy )
    unless match, trailing_nulls
    $I0= 0
split:

trailing_nulls:

return:
    .return( a_directories )
.end


## TODO unfinished
.sub 'catpath' :method
    .param string volume
    .param string directory
    .param string file

    ## TODO
    '_E_not_yet_implemented'()
.end


## TODO unfinished
.sub 'abs2rel' :method
    '_E_not_yet_implemented'()
.end


## TODO unfinished
.sub 'rel2abs' :method
    '_E_not_yet_implemented'()
.end


.sub 'VERSION' :method
    .local pmc version
    version= get_global 'VERSION'
    .return( version )
.end


## TODO more functions

.sub '_fixup_args'
    '_E_not_yet_implemented'()
.end


## throw an error that the sub isn't yet implemented
.sub '_E_not_yet_implemented'
    new $P0, 'Exception'
    $P0 = 'not yet implemented'
    throw $P0
.end

# Local Variables:
#   mode: pir
#   fill-column: 100
# End:
# vim: expandtab shiftwidth=4 ft=pir:
