#!/bin/csh -f

# Invoked as pushf:

# For each pair of file names file1 and file2 in the argument list
# push the contents of file2 onto file1 and move file1 onto a stack.
# The file name for saving the contents of file1 is "file1.stacked"
# followed by as many tildes as necessary to obtain a file not
# currently existing.  If there is no second file argument or file2 is
# nonexistent, file1 becomes a nonexistent file.  If file1 does not
# exist, an empty file is stacked and a second empty file is created
# with ".noexist" appended to the name so that popping can work
# correctly.

# Invoked as popf:

# For each file in the argument list, replace it with the contents of
# the existing file whose name is formed by appending ".stacked" and
# as many tildes as possible, and remove the stacked file that was
# used.  The file named in the argument list is also removed if there
# is a file with ".noexist" appended to the name of the stacked file.

# Invoked as popfn:

# The last argument is a nonnegative integer telling how many times to
# apply popf to the other arguments.

# Invoked as popfall:

# For each file in the argument list, apply popf repeatedly until no
# stacked versions remain.

switch ($0)
case *pushf:
  while ($#argv > 0)
    pushfinternal $1 $1.stacked
    set pushfinternalstatus = $status
    if ($pushfinternalstatus) then
      echo "pushf: Saving $1 on stack using pushfinternal failed; aborting."
      exit $pushfinternalstatus
    endif
    if ($#argv > 1) then
      if (-e $2) then
        echo "pushf: Copying $2 to $1."
        cp $2 $1
      else
        echo "pushf: $2 does not exist, so $1 will remain nonexistent."
      endif
      shift
#    else
#      echo "pushf: $1 will remain nonexistent."
    endif
    shift
  end
  breaksw
case *pushfinternal:
  if (-e $2) then
    pushfinternal $1 $2~
    if ($status) exit $status
  else
    if (-e $1) then
      echo "pushf: Moving $1 to $2."
      mv $1 $2
      set mvstatus = $status
      if ($mvstatus) then
        echo "pushf: Move failed."
        exit $mvstatus
      endif
    else
      echo "pushf: Making $2 a placeholder for a nonexistent file."
      touch $2
      touch $2.noexist
      set touchstatus = $status
      if ($touchstatus) then
        echo "pushf: Touching $2.noexist failed."
        exit $touchstatus
      endif
    endif
  endif
  breaksw
case *popf:
  foreach file ($*)
    if (-e $file.stacked) then
      popfinternal $file.stacked
      if ($status) exit $status
    else
      echo "popf: No stacked version of $file to restore."
    endif
  end
  breaksw
case *popfinternal:
  if (-e $1~) then
    popfinternal $1~
    if ($status) exit $status
  else
    echo "popf: Restoring $1:r from $1."
    rm -f $1:r
    mv $1 $1:r
    set mvstatus = $status
    if ($mvstatus) then
      echo "popf: Move of $1 to $1:r failed."
      exit $mvstatus
    endif
    if (-e $1.noexist) then
      rm -f $1:r
      rm $1.noexist
      set rmstatus = $status
      if ($rmstatus) then
        echo "popf: Restoration from `nonexistent' $1 failed."
        exit $rmstatus
      endif
    endif
  endif
  breaksw
case *popfn:
  set files = ""
  set times = 0
  while ($#argv > 1)
    set files = "$files $1"; shift
  end
  if ($#argv > 0) set times = $1
  if ($times == 0) exit
  popf $files
  popfn $files `expr $times - 1`
  breaksw
case *popfall:
  foreach file ($*)
    while (-e $file.stacked)
      popf $file
      if ($status) exit $status
    end
  end
  breaksw
endsw
