#!/bin/sh

#    Oct 10/97 - F.Majaess (Add "rmveor" switch)
#    Dec 08/95 - F.Majaess (Replace 'hostname' calls by "$HOSTID")
#    Oct 19/95 - F.Majaess (Revise for ibm "file" output for binary files)
#    Apr 01/92 - E. Chan: recognize shell scripts as ascii files
#    Sep 25/91 - E. Chan

#id  copyf   - copies contents of one file into another with extra features 
#id            to handle sections of ascii text and emulation of Fortran
#id            (or COS) file pointer positioning

#    AUTHOR  - E. Chan

#hd  PURPOSE - "copyf" appends a specified number of sections of ascii text
#hd            from the input file onto the output file and keeps track of 
#hd            the number of lines copied. This emulates the file pointer 
#hd            positioning of Fortran (or COS). If the input file does not
#hd            contain ascii text, the contents are simply copied into the 
#hd            output file using the standard UNIX cp operation. This means
#hd            that all non-ascii files are always automatically rewound by 
#hd            UNIX after they are closed. 
#hd 
#hd            The strings '*EOR' and '*EOF' are recognized by the script as
#hd            partitions separating different sections of text. "Copyf"  
#hd            copies any number of sections separated by '*EOR' up to but 
#hd            not including the string '*EOF'.
#hd            The last "*EOR" (if present) will be stripped off if 
#hd            "rmveor" switch is "yes".
#hd 
#hd            If the input file is not specified, the file 'Input_Cards' is
#hd            used as the default. 'Input_Cards' is a file which contains the
#hd            input card images for all CCRN programs invoked in a job. If 
#hd            the output file is not specified, then standard output is 
#hd            used instead.
#hd 
#hd            "Copyf" emulates Fortran (or COS) file pointer positioning
#hd            by accumulating the copied sections in a separate file and
#hd            replacing the original input file with the remaining uncopied
#hd            lines. Subsequent copy operations on the same input file name
#hd            will result in the further editing of these two files.
#hd            A subsequent "rewind" operation is just a concatenation of 
#hd            the two files back into the original file.  
#hd 
#hd            This script is designed to emulate the ascii text handling
#hd            capabilities of the "copyf" operation under the Cray 
#hd            Operating System. The recognition of the string '*EOF' as
#hd            a partition marker is an added feature. 

#pr  PARAMETERS:
#pr 
#pr    PRIMARY
#pr 
#pr      i      = name of input file (='Input_Cards')
#pr      o      = name of output file (default: standard output)
#pr  
#pr    PRIMARY/SECONDARY
#pr 
#pr      nf     = number of sections ending with '*EOR' to be copied -- also
#pr               may be used as a switch to enable copying of all sections
#pr               up to but not including the string '*EOF' (=1/'nf')
#pr
#pr      rmveor = switch controlling the stripping off of the last "*EOR"
#pr               occurence (if present) from the output file provided the 
#pr               input is an ascii file (=no/yes)

#ex  EXAMPLES:
#ex    
#ex   1) copyf i=file1 o=file2 nf=3
#ex 
#ex      The above example copies three sections ending with the string 
#ex      '*EOR' from 'file1' to the end of 'file2'. 'File1' is left with
#ex      the first three sections stripped away. 
#ex    
#ex   2) copyf i=file1 nf
#ex 
#ex      The above example copies all sections (i.e. all lines) up to but
#ex      not including the string '*EOF' from 'file1' to standard output. 
#ex 
#ex   3) copyf o=file2
#ex 
#ex      The above example copies one section from the file 'Input_Cards'
#ex      to 'file2'. 

#  * Reset field separators (otherwise those defined in the parent process
#  * will be used and these may cause problems if they include special 
#  * characters used in this script). 

IFS=' '
export IFS

#  * Obtain the file names and any specified option.
 
arg_list=$@
for arg in $arg_list
do 
  case $arg in
     i=*) eval "$arg"                             ;;
     o=*) eval "$arg"                             ;;
    rmveor=*)  eval "$arg"                        ;;
    nf=*) nf=`expr $arg : 'nf=\([0-9]*\)'`        ;;
    rmveor) rmveor='yes'                          ;;
      nf) nf='nf'
  esac
done

#  * Set variable 'AWK' to the version of "awk" to be used.

AWK=${AWK:='awk'}

# Set the defaults. 

i=${i:=Input_Cards}
o=${o:=Standard_Output}  
nf=${nf:=1}
rmveor=${rmveor:='no'}

#  * Verify that the input file exists.

if [ ! -f "$i" ] ; then
  echo "Abort in COPYF: file $i does not exist"
  exit 1
fi

#
#  * Case 1: Non-ascii file.
#

#  * Perform a standard UNIX cp operation if the data is not ascii text.

info=`file $i 2>/dev/null `
infox=`expr "$info" : '.*\(data.*\).*'`
if [ "$infox" != 'data or International Language text' ] ; then
 file_status=`expr "$info" : '.*\(text\).*'`
 file_status=${file_status:=`expr "$info" : '.*\(character\).*'`}
 file_status=${file_status:=`expr "$info" : '.*\(script\).*'`}
fi

if [ -z "$file_status" ] ; then

  if [ "$o" = 'Standard_Output' ] ; then

    echo "Abort in COPYF: cannot copy non-ascii data in file $i"
    echo "                to standard output."
    exit 2

  elif [ "$nf" != 'nf' ] ; then

    echo "Abort in COPYF: cannot do a partial copy of non-ascii data" 
    echo "                from file $i to file $o."
    exit 3

  else

    cp $i $o
    echo "Warning in COPYF: non-ascii data in file $i, UNIX cp"
    echo "                  performed instead." 
    exit 0

  fi 

fi

#
#  * Case 2: Ascii text file. 
#

#  * Emulate Fortran (or COS) file pointer positioning by splitting up the
#  * input file into two parts. The first part contains the sections to be
#  * copied and the second part contains the lines that will replace those
#  * in the input file.

if [ "$nf" != 'nf' ] ; then

  #  * Case 2a: Copy 'nf' number of sections up to but not including
  #  *          the string '*EOF'. 

  #  *          Generate an awk script to split the input file. The file
  #  *          'Part1' contains sections up to but not including the string
  #  *          '*EOF'. The remaining lines are placed into file 'Part2'.

  cat > Script <<..End
  #                               
  # Set flag and open necessary files.
  #
  BEGIN {
    flag = "false" 
    printf > "Part1"
    printf > "Part2"
  }
  # Trip flag if '*EOF' is encountered.
  #
  /^\*EOF/ { flag = "true" }
  #    
  # Redirect copying of the input file to the appropriate temporary files.
  { 
    if ( n < $nf && flag == "false" )
      print > "Part1"
    else
      print > "Part2"  
  }
  # Increment counter by 1 for each '*EOR' encountered.
  #
  /^\*EOR/ { ++n }            
  #
..End

  $AWK -f Script $i

else

  #  * Case 2b: Copy all lines up to but not including the string '*EOF'.

  #  *          Generate a sed script to split the input file into the 
  #  *          two parts. 

  cat > Script <<..End
  /^\*EOF/,\$b label
  w Part1
  b                                 
  :label
  w Part2
..End

  sed -n -f Script $i

fi

#  * Generate output.

if [ "$o" != 'Standard_Output' ] ; then 
 if [ "$rmveor" = 'yes' ] ; then
  cat Part1 | sed -n -e '$s/^\*EOR/\*EORX/' -e '/^\*EORX/d' -e '1,$p' >> $o 
 else
  cat Part1 >> $o 
 fi
else
 if [ "$rmveor" = 'yes' ] ; then
  cat Part1 | sed -n -e '$s/^\*EOR/\*EORX/' -e '/^\*EORX/d' -e '1,$p'
 else
  cat Part1
 fi
fi 

#  * 'Part2' is moved into the original input file and 'Part1' is
#  * appended onto a file generated with the original input filename and the
#  * extension '_Copied_Lines'. A COS rewind operation is then just a 
#  * concatenation of these two files back together again. 

#  * If input is taken from the file 'Input_Cards' (used as the equivalent
#  * of COS standard input) then there is no need to keep the copied lines
#  * because COS standard input cannot be rewound.

mv Part2 $i 

if [ "$i" != 'Input_Cards' ] ; then
  cat ${i}_Copied_Lines Part1 > Part2 2> /dev/null
  mv Part2 ${i}_Copied_Lines
fi
 
#  * Remove scratch files.

rm -f Script Part*

exit
