# Convert gopher lawn records to TSV format.
# Version 1
#
# Usage: awk -f lawn2tsv.awk gopher-lawn/db/* >lawn.tsv

function encode(str) {
   gsub(/\t/, "\\t", str)
   gsub(/\r/, "\\r", str)
   gsub(/\n/, "\\n", str)
   return str
}

BEGIN {
   RS = ""
   FS = "\n"
   delete header
   delete seen
}

# Print TSV header before processing the first record

NR == 1 {
   j = 0
   for (i = 1; i <= NF; i++) {
       result = match($i, /^[^:]*: /)
       len = RLENGTH
       if (!result) {
           print "Error: Malformed line \"" $i "\""
           exit -1
       }
       name = substr($i, 1, len - 2)
       if (seen[name] > 0) {
           print "Error: Duplicate field name \"" name "\""
           exit -1
       }
       seen[name] = 1
       j++
       header[j] = name
       if (j == 1) {
           printf "%s", name
       } else {
           printf "\t%s", name
       }
   }
   print ""
}

# Process each gopher lawn record
{
   delete blocks
   delete values

   name = ""
   for (i = 1; i <= NF; i++) {
       # Process blocks and line continuations

       result = match($i, /^ +/)
       if (result) {
           text = substr($i, RLENGTH + 1)
           if (length(value) == 0) {
               # nothing to continue yet
               value = text
           } else if (blocks[name] == 1) {
               # block
               value = value "\n" text
           } else {
               # line continuation
               value = value " " text
           }
           values[name] = value
           continue
       }

       # Process empty value with only a field name

       result = match($i, /^[^:]*:$/)
       if (result) {
           name = substr($i, 1, RLENGTH - 1)
           value = ""
           if (seen[name] < 1) {
               print "Error: Unexpected field name \"" name "\""
               exit -1
           }
           values[name] = value
           continue
       }

       # Process field name & value pair

       result = match($i, /^[^:]*: /)
       len = RLENGTH
       if (!result) {
           print "Error: Malformed line \"" $i "\""
           exit -1
       }
       name = substr($i, 1, len - 2)
       value = substr($i, len + 1)
       if (seen[name] < 1) {
           print "Error: Unexpected field name \"" name "\""
           exit -1
       }
       if (value == "\\") {
           blocks[name] = 1
           value = ""
       }
       values[name] = value
   }

   # Print TSV row

   for (i = 1; i <= j; i++) {
       name = header[i]
       value = encode(values[name])
       if (i == 1) {
           printf "%s", value
       } else {
           printf "\t%s", value
       }
   }
   print ""
}