#!/usr/bin/mawk -We
# *********************************************************************
# tabletolist: convert from NoSQL 'table' to 'list' format.
# Copyright (c) 1998,2006 Carlo Strozzi
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 dated June, 1991.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# *********************************************************************
#  $Id: tabletolist,v 1.6 2006/03/10 11:26:13 carlo Exp $

BEGIN {
  NULL = ""; FS = OFS = "\t"; unescape = 1; cont = "\n\t"

  # Get local settings.
  nosql_install = ENVIRON["NOSQL_INSTALL"]
  stdout = ENVIRON["NOSQL_STDOUT"]
  stderr = ENVIRON["NOSQL_STDERR"]

  # Set default values if necessary.
  if (nosql_install == NULL) nosql_install = "/usr/local/nosql"
  if (stdout == NULL) stdout = "/dev/stdout"
  if (stderr == NULL) stderr = "/dev/stderr"

  while (ARGV[++i] != NULL) {
     if (ARGV[i] == "-p" || ARGV[i] == "--prefix") pfx = ARGV[++i]
     else if (ARGV[i] == "-n" || ARGV[i] == "--no-unescape") unescape = 0
     else if (ARGV[i] == "-C" || ARGV[i] == "--chop") no_hdr = 1
     else if (ARGV[i] == "-N" || ARGV[i] == "--no-header") no_hdr = 1
     else if (ARGV[i] == "-c" || ARGV[i] == "--chomp") no_foot = 1
     else if (ARGV[i] == "-F" || ARGV[i] == "--no-footer") no_foot = 1
     else if (ARGV[i] == "-j" || ARGV[i] == "--justify") justify = 1
     else if (ARGV[i] == "-t" || ARGV[i] == "--trim") trim = 1
     else if (ARGV[i] == "-i" || ARGV[i] == "--input") i_file = ARGV[++i]
     else if (ARGV[i] == "-o" || ARGV[i] == "--output") o_file = ARGV[++i]
     else if (ARGV[i] == "-m" || ARGV[i] == "--mux") cont = "\n@"
     else if (ARGV[i] == "-h" || ARGV[i] == "--help") {
	system("grep -v '^#' " nosql_install "/help/tabletolist.txt")
	exit(rc=1)
     }
     else if (ARGV[i] == "--show-copying") {
	system("cat " nosql_install "/doc/COPYING")
	exit(rc=1)
     }
     else if (ARGV[i] == "--show-warranty") {
	system("cat " nosql_install "/doc/WARRANTY")
	exit(rc=1)
     }
  }

  ARGC = 1					# Fix argv[]

  if (o_file == NULL) o_file = stdout
  if (i_file != NULL) { ARGV[1] = i_file; ARGC = 2 }
}

NR == 1 {
   gsub(/\001/, "")			# Remove SOH markers
   gsub(/ +/, "")			# trim blanks in names
   ncol = split($0, C)
   i=0
   while (++i <= ncol)
	if (length(C[i]) > max_width) max_width = length(C[i])
   next
}

{ gsub(/ +\t/,"\t"); sub(/ +$/,NULL) }	# trim trailing blanks.

{
  if (NR == 2) {
     if (!no_hdr) print NULL > o_file
  }  else print NULL > o_file

  for (i = 1; i <= ncol; i++) {

    # Unescape tabs and newlines first.

    if (unescape) $i = nosqlUnescape($i)

    # Add the proper trailing char tab to newlines,
    # unless '-j' was requested.

    if (!justify) gsub(/\n/, cont, $i)
    else {
       pad = " "
       for (j=1; j<=max_width; j++) pad = pad " "
       gsub(/\n/, "\n" pad, $i)
    }

    if (trim) {
       sub(/^ +/, NULL, C[i]); sub(/ +$/, NULL, C[i])
       sub(/^ +/, NULL, $i); sub(/ +$/, NULL, $i)
    }
    if (justify) {
       printf("%s%s", pfx, C[i]) > o_file
       for (j=length(C[i]); j<max_width; j++) printf(" ") > o_file
       printf(" %s\n", $i) > o_file
    }
    else printf("%s%s\t%s\n", pfx, C[i], $i) > o_file
  }
}

END {
  if (rc) exit(rc)
  # Handle empty input table.
  if (NR == 1) {
    if (!no_hdr) print NULL > o_file
    for (i = 1; i <= ncol; i++) {
       printf("%s%s\n", pfx, C[i]) > o_file
    }
  }
  if (!no_foot) print NULL > o_file
}

#
# Function section.
#

# *********************************************************************
# nosqlUnescape(string)
#
# Takes a string and translates any unescaped '\t' and '\n' strings
# into physical tabs and newlines respectively. Returns the converted
# string.
# *********************************************************************
function nosqlUnescape(s,		S,i,s_length,a,escaped) {
  s_length = split(s, a, "")
  s_length++                # Cope with s_length==1
  while ( ++i <= s_length ) {
    if ( a[i] == "\\" && !escaped ) { escaped = 1; continue }
    if ( a[i] == "n" && escaped ) { S = S "\n"; escaped = 0; continue }
    if ( a[i] == "t" && escaped ) { S = S "\t"; escaped = 0; continue }
    if ( escaped ) { S = S "\\" a[i]; escaped = 0; continue }
    S = S a[i]
  }
  return S
}

# EOF
