#! /usr/bin/gawk -f
# Last edited on 2014-03-19 00:34:12 by stolfilocal

# Reads a slumber data file and writes to standard output 
# a list of calls to {make_dot_cmds}, one per dot.

BEGIN \
  { abort = -1;
    if (csep == "") { arg_error(("must define {csep}")); }
    if (tmin == "") { arg_error(("must define {tmin}")); }
    if (tcol == "") { arg_error(("must define {tcol}")); }
    if (cols == "") { arg_error(("must define {cols}")); }
    
    # Check hour column index and min value:
    tcol = check_num(tcol, "arg", "tcol", 1, 999);
    tmin = check_num(tmin, "arg", "tmin", 0, 9999999);
    
    # Split and check the columns to extract:
    gsub(/[ ]/, "", cols);
    ncols = split(cols, icol, ",");
    for (i = 1; i <= ncols; i++) 
      { icol[i] = check_num(icol[i], "arg", ("icol[" i "]"), 1, 999); }
      
    NF_exp = 28; # Data lines must have this number of fields.
  }
 
(abort >= 0) { exit abort; }
 
/[!]/ \
  { next; }

/^[ ]*([\#]|$)/ \
  { next; }
  
 
/^[ ]*201[0-9]-[01][0-9]-[0-3][0-9] / \
  { # Remove trailing comments:
    gsub(/[ ]*[#].*$/, "", $0); 
    
    # Remove suffix "+" or "-" on unknown values:
    if ($0 ~ /[-+][ ]*([|]|$)/) { data_warning(("suffix '+'or '-' removed")); }
    gsub(/[-+][ ]*[|]/, " |", $0); 
    gsub(/[-+][ ]*$/, "", $0); 
    
    # Consistency checks:
    if (NF != NF_exp) { data_error(("wrong field count")); }
    if ($2 != "19:00:00") { data_error(("expected «19:00:00» on column 2 found «" $(2) "»")); }
    for (i = 3; i <= NF-1; i += 2) 
      { if ($(i) != "|") { data_error(("expected '|' on column " i " found «" $(i) "»")); } }
    
    # Get time and select:    
    t = check_num($(tcol), "data", ("$(" tcol ")"), 0, 999999);
    if (t < tmin) { next; }
    
    # Output selected fields:
    for (i = 1; i <= ncols; i++) 
      { if (i > 1) { printf "%s", csep; }
        k = icol[i];
        if (k > NF) { data_error(("invalid column index " k)); }
        printf "%s", $(k);
      }
    printf "\n";
    next;
  }

// \
  { data_error(("invalid format")); }
  
function check_num(x,kind,name,xmin,xmax,  xnum,msg)
  { # Removes lead/trail blanks of {x}, then checks if it a number, integer or float (not exp),
    # in the range {[xmin _ xmax]}.  If yes, returns {x} numerified. If not, prints {arg_error} or {data_error}.
    # depending on {kind}.
    gsub(/^[ ]+/, "", x);
    gsub(/[ ]+$/, "", x);
    msg="";
    if (x !~ /^[-+]?[0-9]*([0-9][.]?|[.][0-9]+)$/) { msg = ("invalid {" name "} = «" x "»"); }
    xnum=x+0;
    if ((xnum < xmin) || (xnum > xmax)) { msg = ("value {" name "} = «" x "» should be in [" xmin " _ " xmax "]"); }
    if (msg != "") { if (kind == "arg") { arg_error(msg); } else { data_error(msg); } }
    return xnum;
  }
           
function arg_error(msg)
  { printf "** %s\n", msg > "/dev/stderr"; 
    abort = 1;
    exit(abort);
  } 
 
function data_error(msg)
  { printf "%s:%s: ** %s\n", FILENAME, FNR, msg > "/dev/stderr"; 
    printf "  «%s»\n", $0 > "/dev/stderr"; 
    abort = 1;
    exit(abort);
  } 
         
function data_warning(msg)
  { printf "%s:%s: !! warning: %s\n", FILENAME, FNR, msg > "/dev/stderr"; 
    printf "  «%s»\n", $0 > "/dev/stderr"; 
  }