#!/usr/local/bin/perl
#
# "fmerge"	K. J. Turner	04/12/95
#
# Original due to Tommy Persson (tpe@ida.liu.se), 14/12/92

# If necessary, save the original FrameMaker file in MIF format first as
# "file.merge.framemif". (The MIF extension may be changed in the code below.)
#
# Then do:
# 
#   fmerge file.merge[.framemif]
#
# The result will be an output file called "file.framemif" which can be read
# into FrameMaker again.
#
# The input may contain fields of the following form:
#
#   $data	followed by the name of a file with merge data
#   $next	read next line of merge data (e.g. for a sheet of labels)
#   $field	name of field to be replaced by value in merge data
#
# The field marker "$" may be changed in the code below.
#
# The merge data has the form:
#
#   field_name,field_name,...
#   field_value,field_value,...
#   field_value,field_value,...
#   ...
#
# The field separator "," may be changed in the code below. Field names are
# alphanumeric (including "_").
#
# Embedded graphics and frames may cause odd effects in the output because
# they are (incorrectly) shared between the copied pages. They may not
# appear on the screen but the printed version should be OK.

$prog = $0;
$prog =~ s/.*\///g;

$field_marker = "\\$";
$field_separator = ",";
$mif = ".framemif";

$old_file = $ARGV[0];
$old_file =~ s/$mif//;
if ("$old_file" eq "") {
  &abort("usage: $prog file.merge[$mif]");
}

$HOME = $ENV{'HOME'};			# find home directory
$tmp_dir = "$HOME/.NeXT/.NextTrash";
$new_file = "$old_file";
$new_file =~ s/\.merge//;

undef $/;					# multi-lines for file
$* = 1;

open(OLDMIF, "$old_file$mif") ||
    &abort("Cannot open $old_file$mif: $!");

open(NEWMIF, ">$new_file$mif") ||
    &abort("Cannot open $new_file$mif: $!");

$_ = <OLDMIF>;
/<TextFlow/ ||					# find start of body text
    &abort("No text in $old_file$mif");
print NEWMIF $`;				# output initial definitions
$old_body = $& . $';				# save original body text

$/ = "\n";					# single lines for merge data
$* = 1;

$curr_filename = "";				# no merge data file initially
$field_num = 0;					# no fields initially

while (1) {					# loop till out of merge data
  $_ = $old_body;
  while (/$field_marker(\w*)/) {	# loop till no more fields
    print NEWMIF $`;				# output file up to field
    $field = $1;				# save field name
    $rest = $';					# save what is after field
    if ($field eq "data") {			# read merge data if new
      $_ = $rest;				# reset input
      /\s*([^\s'$field_marker]*)/;		# extract filename
      $field = $1;				# save filename
      $rest = $';				# save what is after field
      if ($field ne $curr_filename) {		# new file to open?
        if ($curr_filename) {			# close existing file?
	  close DATA;
	}
	open(DATA, "$field") ||
	  &abort("Cannot open $field: $!");
	$curr_filename = $field;
        &read_non_blank;			# read till next entry
	$field_num = split (/$field_separator/, $data);	# set number of fields
	@field_name = @_;			# set names of fields
        &read_non_blank;			# read till next entry
        !eof || last;				# finish data loop if EOF
	&read_fields;				# read first line of data
      }
    }
    elsif ($field eq "next") {			# read next merge data
      &read_fields;
    }
    else {					# replace field name
      $i = 0;
      while (($i < $field_num) && (@field_name[$i] ne $field)) {
	$i++;					# loop till name match or end
      }
      if ($i < $field_num) {			# field name found?
	print NEWMIF @field_value[$i];		# output field value
      }
      else {
	print NEWMIF "$field_marker$field";	# output unknown field name
      }
    }
    $_ = $rest;					# reset input
  }						# end of field loop
  s/$field_marker(\w*)//g;			# remove any fields left
  print NEWMIF $_;				# output rest of file
  !eof || last;					# finish data loop if EOF
  &read_fields;					# read next line of data
}						# end of merge data loop

if ($curr_filename) {
  close DATA;
}

close NEWMIF;

close OLDMIF;

#
# Subroutines
#

# abort program with message

sub abort {
  die ("$prog: *** $_[0] ***\n");
}

# read fields of merge data

sub read_fields {
  @field_value = split (/$field_separator/, $data);	# set values of fields
  &read_non_blank;					# read till next entry
}

# read till non-blank line of merge data

sub read_non_blank {
  while (($data = <DATA>) =~ /^\s+$/) {		# read till non-blank
  }
  chop ($data);					# remove trailing newline
}
