#  FILE NAME is 'awk_split'
#
# @(#)awk_split	2.6 84/06/13
#
#  This awk file is called by the script fortsplit.
#
#  This awk file breaks up a large .f file into files containing single
#  routines which are named by concatenating the routine name with '.f'.
#  Routines are broken up by searching for the strings PROGRAM, FUNCTION,
#  SUBROUTINE, REAL FUNCTION, COMPLEX FUNCTION, INTEGER FUNCTION, LOGICAL
#  FUNCTION, CHARACTER FUNCTION, DOUBLE COMPLEX FUNCTION, DOUBLE PRECISION
#  FUNCTION, or BLOCK DATA in the large file.  These strings may or may not
#  be separated by blanks, and the typed ones may or may not have length
#  numbers associated with them.  In each case, an editor command 
#  to print all lines from the last 'END' statement to the next 'END' statement
#  after the routine name line to a file is generated.  If the current
#  routine line is the first in the file, all lines from the beginnng of
#  the file to the 'END' statement following this routine name line will
#  be printed to the file.  These lines will be printed to a file whose name
#  is that of the routine.  
#
#  Lines are printed from 'END' statement to 'END' statement so that any 
#  comment or compiler option lines appearing before the routine name statement
#  will be preserved at the beginning of the newly created file containing
#  that routine.
#
#  In the case of a block data subroutine, the file name generated is of the
#  form number.f where number is simply a counter which is incremented
#  each time it is used.
#
#  After writing this portion of the file, a line counter, which is used to
#  determine the beginning line of the next file, is incremented to point to
#  the line directly following the 'END' statment which initiated the previous
#  write.
#
#  At this point, the routine name followed by '.o' is written into the
#  make file which is also being generated at the same time.
#  At least 2 make files are generated for each program processed by this 
#  awk file.  The last make file generated is used as a master make file to 
#  drive the other make files.  The other make files operate on up to 50
#  routines each.  In general, these make files will get source files from 
#  SCCS for a given routine, create a corresponding object file, and, when
#  all routines have object files, link them together into relocatable 
#  segments.  The master make file then links all of these segments together
#  with appropriate libraries in order to form an executable routine.
#
#  This awk script creates one large file, called makefile1, which contains
#  all of the described make files.  Another awk file, make_split, is used
#  to break up this large file into the routine make file(s) and the master
#  make file.

#  In the case where the first line of the file is not PROGRAM, FUNCTION, or
#  SUBROUTINE, a PROGRAM line is generated and the routine is written to 
#  the file 'main.f' and an entry is made in the make file of 'main.o'.
#
#  The BEGIN statements generate the composite make file which will be appended
#  to during execution of the awk file and initialize several flags.
#
#  The file 'file.list' is used to keep a list of all of the source files
#  which will be generated during this process.  It is used by the driving
#  shell script, 'fortsplit' to enter these files, as well as the routine make
#  files, into an SCCS directory in the current directory.
#
#  The following lines are found at the top of each routine make file...
#
#      # Makefile #X
#      NAME = ../X.obj
#      OPERATION1 = fc
#      FFLAGS = -c -U
#      LFLAGS = -M18384
#      LISTING =
#
#      OBJECTS = \
#
#  A comment line is generated at the top of each routine make file so that
#  boundaries between routine make files can easily be found when splitting
#  up the composite make file.  Each routine make file is named by a number
#  followed by the string '.make' and this number is incremented each time
#  a new routine make file is begun ('oname').
#
#  The NAME variable is the name of the file which results from the make 
#  operation on the routines.  The master make file looks for these resulting
#  files from the routine make files in order to link all the object files
#  and create an executable routine.
#
#  OPERATION1 is done to the source files during the routine make in order
#  to create the NAME file.  This operation can be changed by calling the
#  routine make from the master make with a different string for OPERATION1. 
#  The default for OPERATION1 is a FORTRAN compile, in which FFLAGS is used 
#  to pass options to the compiler ( -c and -U in the default case).  Finally,
#  LFLAGS is used to pass options to the linker.  This is usually blank, or
#  designates a maximum size for a code segment.  LISTING is a variable which
#  is used in the case when the Softool AUDITOR is not available and the
#  FORTRAN compiler option for a long listing is used instead.  Here, the long
#  listing will be sent to a file designated by LISTING instead of to standard
#  out, the CRT.
#
BEGIN { 
        makefile = "makefile1"; 
        rfiles = "file.list";
        oname = 1;
        objectname = oname ".obj";
        directory = oname ".dir";
        print ( "# Makefile #" oname ) >> makefile;
        print ( "NAME = ../1.obj" ) >> makefile;
        print ( "OPERATION1 = fc" ) >> makefile;
	print ( "FFLAGS = -c -U" ) >> makefile;
	print ( "LFLAGS = -M16384" ) >> makefile;
	print ( "LISTING =" ) >> makefile;
        print ( " " ) >> makefile;
        print ( "OBJECTS = \\" ) >> makefile; 
        firstime =1;
        counter = 1; 
        linecount = 0;
        commentflag = 0;
        added = 0;
        no_obj = 0;
        newbegin = 1;
      }
{
#
#  If there are comment lines at the beginning of the file, they are
#  skipped and the search continues for the first non-comment line in the
#  file.  If this line is not a PROGRAM, SUBROUTINE, or FUNCTION (any kind),
#  a PROGRAM line is generated as the first line in the file.  Further, this
#  routine will be written to a file called 'main.f'.
#
    if (firstime == 1) 
     {
        if (( substr ( $0,1,1 ) ~ /[Cc\*\$D]/ ) || ( $0 ~ /^$/))
          {
             linecount++;
             next;
          };
#
        if ( ($0 !~ /^[ 	]*(PROGRAM|FUNCTION|SUBROUTINE).*/) && \
	 ($0 !~ /^[ 	]*(REAL|COMPLEX|INTEGER|LOGICAL|CHARACTER)[ 	]*[\*]?[ 	]*[0-9]*[ 	]*FUNCTION.*/) && \
	 ($0 !~ /^[ 	]*DOUBLE[ 	]*(COMPLEX|PRECISION)[ 	]*[\*]?[ 	]*[0-9]*[ 	]*FUNCTION.*/) && \
	 ($0 !~ /^[ 	]*BLOCK[ 	]*DATA.*/) )
	  {
            linecount++;
            print ( 1 );
	    print ( "i" );
	    print ( "      PROGRAM MAIN" );
	    print ( "." );
            added = 1;
          };
#
#  The first routine file name is generated (either 'main.f' or a file named
#  after the routine), and the flag 'firstime' is cleared to indicate that
#  the first routine has been found.  In addition, the appropriate entry
#  is made to the first routine make file.  Note that the edit commands to
#  write this routine are not generated until its associated 'END' statement 
#  is found.
#
	for ( i=0; i < length; i++ )
	  {
	    if ( substr ( $0,i,7 ) == "PROGRAM" )
	      {
                i += 7;
		break;
              }
            else if ( substr ( $0,i,8 ) == "FUNCTION" )
	      {
		i += 8;
		break;
              }
            else if ( substr ( $0,i,10 ) == "SUBROUTINE" )
	      {
		i += 10;
		break;
              };
          }
        for (; i < length; i++ )
	  {
	    if ( substr ( $0,i,1 ) !~ /[ 	]/)
	      break;
          }
        for ( j = i; j <= length; j++ )
	  {
	    if ( substr ( $0,j,1 ) ~ /[ 	\(]/ )
	      {
		j--;
		break;
              }
            else if ( substr ( $0,j,1 ) == " " )
              {
                j--;
                break;
              };
          }
        if (( j - i + 1 ) > 10 )
          filename = substr ( $0,i,10 )
        else
          filename = substr ( $0,i,(j-i+1) );
        if ( added == 1 )
          {
            filename = "main";
            added = 0;
          };
        linecount++;
        print ( "	" filename ".o\\" ) >>makefile;
        print ( directory "/" filename ".f" ) >>rfiles;
        no_obj++;
        firstime = 0;
      }
#
#  If this is not the first routine, the line is checked to see if it 
#  contains any keyword routine type, except BLOCK DATA, as the first field.
#  The problem here is that the type, length if applicable, and name can all
#  be strung together in FORTRAN; this makes it difficult to extract the
#  routine name.  This loop searches the entire line for the string following
#  the keywords PROGRAM, ROUTINE, or FUNCTION.  Once the beginning of this
#  string is found, it searches for the next blank, or an opening parenthesis
#  to extract the actual routine name.  (Searching for a blank or paren takes
#  care of strings like 'SUBROUTINExyzzy(plover)'.)  Finally, this string
#  name is used as a name for the file containing the routine.  This name is
#  truncated to 10 characters if necessary.
#
#  The filename is next written to the routine make file.  If this is the 
#  50th name written to the file, this routine make file is terminated and the
#  next begun.  The make file is terminated by the following statements.
#
#       SOURCES = $(OBJECTS:.o=.f)
#
#       .SUFFIXES:  .o .f
#
#       .IGNORE:
#
#       .f.o: 
#      		-$(OPERATION1) $(FFLAGS) $< $(LISTING)
#
#       ALL:  $(OBJECTS)
#   		/bin/ld -r $(LFLAGS) $(OBJECTS) -o $(NAME)
#
#       $(SOURCES):
# 		sccs get $@
#
#  These lines are interpreted as follows.  The SOURCES line means that to
#  generate the SOURCES list, take the OBJECTS list and change all the '.o'
#  suffixes to '.f' suffixes.
#  The .SUFFIXES line means that '.o' files depend on '.f' files.  Next,
#  the .IGNORE line means to continue with the make even if one individual
#  operation fails.  The .f.o line means that to make a '.o' file from a '.f'
#  file, do OPERATION1 with any associated FFLAGS, on all the .f files ('$<' 
#  indicates this).  The next line, ALL, indicates that ALL depends on OBJECTS;
#  and to make ALL it is necessary to link all the OBJECTS using LFLAGS as 
#  flags to the linker and putting the resulting routine into a file indicated
#  by NAME.  Finally, SOURCES are obtained by getting the '.f' files from the
#  SCCS directory.
#
#  After these lines have been written to the make file, the name generation
#  number for the routine make files is incremented and the beginning lines
#  of the next routine make file are written out.
#
#  If this routine was not the 50th routine, its name is simply written to
#  the make file.
#
else if ( ($0 ~ /^[ 	]*(PROGRAM|FUNCTION|SUBROUTINE).*/) || \
      ($0 ~ /^[ 	]*(REAL|COMPLEX|INTEGER|LOGICAL|CHARACTER)[ 	]*[\*]?[ 	]*[0-9]*[ 	]*FUNCTION.*/) || \
      ($0 ~ /^[ 	]*DOUBLE[ 	]*(COMPLEX|PRECISION)[ 	]*[\*]?[ 	]*[0-9]*[ 	]*FUNCTION.*/))
      {
        linecount++;
	for ( i=0; i < length; i++ )
	  {
	    if ( substr ( $0,i,7 ) == "PROGRAM" )
	      {
                i += 7;
		break;
              }
            else if ( substr ( $0,i,8 ) == "FUNCTION" )
	      {
		i += 8;
		break;
              }
            else if ( substr ( $0,i,10 ) == "SUBROUTINE" )
	      {
		i += 10;
		break;
              };
          }
        for (; i < length; i++ )
	  {
	    if ( substr ( $0,i,1 ) !~ /[ 	]/)
	      break;
          }
        for ( j = i; j <= length; j++ )
	  {
	    if ( substr ( $0,j,1 ) ~ /[ 	\(]/ )
	      {
		j--;
		break;
              };
          }
        if (( j - i + 1 ) > 10 )
          filename = substr ( $0,i,10 )
        else
          filename = substr ( $0,i,(j-i+1) );
        print ( directory "/" filename ".f" ) >>rfiles;
        if ( no_obj == 50 )
         {
            print ( "	" filename ".o" ) >> makefile;
            print ( " " ) >>makefile;
            print ( "SOURCES = $(OBJECTS:.o=.f)" ) >> makefile;
            print ( " " ) >> makefile;
            print ( ".SUFFIXES: .o .f " ) >> makefile;
            print (  " " ) >> makefile;
            print (  ".IGNORE: " ) >> makefile;
            print (  " " ) >> makefile;
            print (  ".f.o: " ) >> makefile;
            print (  "	-$(OPERATION1) $(FFLAGS) $< $(LISTING)" ) >> makefile;
            print ( " " ) >> makefile;
            print ( "ALL: $(OBJECTS)" ) >> makefile;
            print (  "	/bin/ld -r $(LFLAGS) $(OBJECTS) -o $(NAME)")\
		      >> makefile;
            print ( " " ) >> makefile;
            print ( "$(SOURCES):" ) >> makefile;
            print ( "	sccs get $@" ) >> makefile;
            oname++;
            directory = oname ".dir";
            objectname = oname ".obj";
            no_obj = 0;
	    print ( "# Makefile #" oname ) >> makefile;
            print ( " " ) >> makefile;
            print ( "NAME = ../" objectname ) >> makefile;
            print ( "OPERATION1 = fc" ) >> makefile;
	    print ( "FFLAGS = -c -U" ) >> makefile;
	    print ( "LFLAGS = -M16384" ) >> makefile;
	    print ( "LISTING =" ) >> makefile;
            print ( " " ) >> makefile;
            print ( "OBJECTS = \\" ) >> makefile; 
         }
        else
         {
            print ( "	" filename ".o\\" ) >> makefile;
            no_obj++;
         };
 }
#
#  In the case of BLOCKDATA routines, these may or may not have names so the
#  awk process generates a name based on the number of block data routines
#  already found.
#
#  The routine name is written to the make file, and if it is the 50th name
#  in the routine make file, that file's terminating statements (see above)
#  are written and the next routine make file begun.
#
else if ( $0 ~ /^[ 	]*BLOCK[ 	]*DATA/ )
 {
   linecount++;
   filename = counter;
   print ( directory "/" filename ".f" ) >>rfiles;
   counter++;
   if ( no_obj == 50 )
    {
      print ( "	" filename ".o" ) >> makefile;
      print ( " " ) >>makefile;
      print ( "SOURCES = $(OBJECTS:.o=.f)" ) >> makefile;
      print ( " " ) >> makefile;
      print (  ".IGNORE: " ) >> makefile;
      print ( " " ) >> makefile;
      print ( ".SUFFIXES: .o .f " ) >> makefile;
      print (  " " ) >> makefile;
      print (  ".f.o: " ) >> makefile;
      print (  "	-$(OPERATION1) $(FFLAGS) $< $(LISTING)" ) >> makefile;
      print ( " " ) >> makefile;
      print ( "ALL: $(OBJECTS)" ) >> makefile;
      print (  "	/bin/ld -r $(LFLAGS) $(OBJECTS) -o $(NAME)")\
               >> makefile;
      print ( " " ) >> makefile;
      print ( "$(SOURCES):" ) >> makefile;
      print ( "	sccs get $@" ) >> makefile;
      oname++;
      directory = oname ".dir";
      objectname = oname ".obj";
      no_obj = 0;
      print ( "# Makefile #" oname ) >> makefile;
      print ( " " ) >> makefile;
      print ( "NAME = ../" objectname ) >> makefile;
      print ( "OPERATION1 = fc" ) >> makefile;
      print ( "FFLAGS = -c -U" ) >> makefile;
      print ( "LFLAGS = -M16384" ) >> makefile;
      print ( "LISTING =" ) >> makefile;
      print ( " " ) >> makefile;
      print ( "OBJECTS = \\" ) >> makefile; 
    }
   else
    {
       print ( "	" filename ".o\\" ) >> makefile;
       no_obj++;
    };

  }
  #
  #  If the line found is an 'END' statement, the editor commands to write
  #  the file are generated.  These commands will write everything from the
  #  line after the last 'END' statement encountered to the current one,
  #  inclusive.  This ensures that any comment lines before the actual routine
  #  statement line, or any compiler options before this line will be 
  #  included in the file.
  #
 else if(( substr($0,1,72) ~ /^[ 	]*[0-9]*[ 	]*END[ 	]*$/) ||\
          ($0 ~ /^[ 	]*[0-9]*[ 	]*END[ 	]*!.*/)) 
  {
    linecount++;
    print ( newbegin "," linecount " w " filename ".f" );
    newbegin = linecount + 1;
  }
 else
   linecount++;
}
#
#  The END statements first generate an editor command to quit (q), and then
#  finish creating the make file.  Since the original file may have been edited
#  to add a beginning PROGRAM statement, the editor command q! is used to exit
#  without re-writing the file.
#
#  If the last routine make file may has less than 50 .o file names in the 
#  object section, a dummy .o file is added as the last logical line in the 
#  OBJECT section.  This line and the preceding logical line extension
#  will be removed before the make file is actually executed.
#
#  The last routine make file is terminated as all the other routine make
#  files have been and the master make file is written.  The master make
#  file will operate by setting up dependencies as follows.
#  ALL depends on OBJECTS and is created by linking OBJECTS, along with
#  appropriate libraries into an executable file.
#
#  OBJECTS are created by running the individual routine make files to 
#  generate relocatable linked files.  Before these make files are called,
#  a directory is created if it doesn't already exist which called by the 
#  numeric name of the make file appended with '.dir', for example '1.dir'.
#  After this directory is created, the appropriate routine make file is
#  copied to it.  Next, the 'PROJECTDIR' variable is set to the current
#  directory and exported.  Then a cd is performed to new directory and the
#  make is executed in this directory.
#
#  By executing the routine level makes in their own separate directories,
#  the size of each directory is limited to the number of '.f', '.o', and 
#  '.make' files associated with each routine level make file.  Since the
#  NAME variable for each routine make file is prefixed by '../', the
#  resulting relocatable object file from each make is placed in the
#  directory containing the SCCS directory, where the final link will occur.
#
#  Note that the '-' preceeding the 'mkdir' and 'PROJECTIDIR' lines causes
#  make to ignore any errors which occur during these times.  Thus, if a
#  directory already exists for a routine make file, the make will proceed
#  anyway.  Likewise, if the link for any routine make file fails, make will
#  continue with the next routine make, or the final link.
#
#  Actions for the routine make files to execute for OPERATION1 and 
#  OPERATION2 are passed to the individual routine make files, as are
#  compiler flags (FFLAGS), linker flags (LFLAGS), and listing flag (LISTING).
#  If these strings are null, their defaults as defined in the individual
#  routine make files are used.
#
#  The master make file lines are...
#
#       # Master makefile
#       
#       NAME = ALL
#       OPERATION1 =
#       FFLAGS =
#       ENTRY = start
#       LFLAGS =
#       LISTING =
#       LIBS =
#       ENDS =
#
#       OBJECTS = \
#      		1.obj\
#		2.obj\ 
#		...
#
#       SOURCES = $(OBJECTS:.obj=.make)
#
#       .SUFFIXES:  .obj .make
#
#       .IGNORE:
#
#       .make.obj:
#               -mkdir $*.dir
#               chmod +w $*; cp $*.make $*.dir
#        	-if [ -d SCCS ]; then PROJECTDIR=`pwd`;
#               else echo {PROJECTDIR:=`pwd`}; fi; export PROJECTDIR;
#               cd $*.dir; make -f $< $(OPERATION1)
#               $(FFLAGS) $(LFLAGS) $(LISTING)
#
#       ALL:  $(OBJECTS)
#		/bin/ld -e $(ENTRY) /lib/frt0.o $(OBJECTS) $(LIBS) -lI77 -lF77
#		       -lc -lm $(ENDS) -o $(NAME)
#
#       $(SOURCES):
#		sccs get $@
#
END { print ("q!" ) ;
      if ( no_obj != 0 )
       {
      print ( "	dummy.o" ) >> makefile;
      print ( " " ) >>makefile;
      print ( "SOURCES = $(OBJECTS:.o=.f)" ) >> makefile;
      print ( " " ) >> makefile;
      print (  ".IGNORE: " ) >> makefile;
      print ( " " ) >> makefile;
      print ( ".SUFFIXES: .o .f " ) >> makefile;
      print (  " " ) >> makefile;
      print (  ".f.o: " ) >> makefile;
      print (  "	-$(OPERATION1) $(FFLAGS) $< $(LISTING)" ) >> makefile;
      print ( " " ) >> makefile;
      print ( "ALL: $(OBJECTS)" ) >> makefile;
      print (  "	/bin/ld -r $(LFLAGS) $(OBJECTS) -o $(NAME)")\
               >> makefile;
      print ( " " ) >> makefile;
      print ( "$(SOURCES):" ) >> makefile;
      print ( "	sccs get $@" ) >> makefile;
       }
      else
          ;
      print ( "# Master makefile" ) >> makefile;
      print ( " " ) >>makefile;
      print ( "NAME = ALL" ) >> makefile;
      print ( "OPERATION1 =" ) >> makefile;
      print ( "FFLAGS =" ) >> makefile;
      print ( "ENTRY = start" ) >> makefile;
      print ( "LFLAGS =" ) >> makefile;
      print ( "LISTING =" ) >> makefile;
      print ( "LIBS =" ) >> makefile;
      print ( "ENDS =" ) >> makefile;
      print ( " " ) >> makefile;
      print ( "OBJECTS = \\" ) >> makefile; 
      for ( i=1; i<oname; i++ )
        print ( "	" i ".obj\\" ) >> makefile;
      print ( "	" oname ".obj" ) >> makefile;	
      print ( " " ) >> makefile;
      print ( "SOURCES = $(OBJECTS:.obj=.make)" ) >> makefile;
      print ( " " ) >> makefile;
      print ( ".SUFFIXES: .obj .make " ) >> makefile;
      print (  " " ) >> makefile;
      print ( ".IGNORE:" ) >> makefile;
      print (  " " ) >> makefile;
      print (  ".make.obj: " ) >> makefile;
      print (  "	-mkdir $*.dir" ) >>makefile;
      print (  "	chmod +w $*.make; cp $*.make $*.dir" ) >> makefile;
      print (  "	-if [ -d SCCS ]; then PROJECTDIR=`pwd`;"\
                       " else echo {PROJECTDIR:=`pwd`}; fi; export PROJECTDIR;"\
                       " cd $*.dir; make -f $< $(OPERATION1)"\
                       " $(FFLAGS) $(LFLAGS) $(LISTING)" ) >> makefile;
      print ( " " ) >> makefile;
      print ( "ALL: $(OBJECTS)" ) >> makefile;
      print (  "	/bin/ld -e $(ENTRY) /lib/frt0.o  $(OBJECTS) $(LIBS)"\
                       " -lI77 -lF77 -lm -lc $(ENDS) -o $(NAME)" ) >> makefile;
      print ( " " ) >> makefile;
      print ( "$(SOURCES):" ) >> makefile;
      print ( "	sccs get $@" ) >> makefile;
    }
