diff options
Diffstat (limited to 'build-aux/csvm2csv')
-rwxr-xr-x | build-aux/csvm2csv | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/build-aux/csvm2csv b/build-aux/csvm2csv new file mode 100755 index 0000000..a67f43e --- /dev/null +++ b/build-aux/csvm2csv @@ -0,0 +1,134 @@ +#!/usr/bin/awk -f +# +# Compiles a "magic" CSV file into a normal CSV +# +# Copyright (C) 2016 R-T Specialty, LLC. +# +# 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, either version 3 of the License, or +# (at your option) any later version. +# +# 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, see <http://www.gnu.org/licenses/>. +# +# "Magic" CSVs simply exist to make life easier: they permit comments, blank +# lines, variables, sub-delimiter expansion, and any number of ranges per line. +# Ranges will be expanded in every combination, making rate tables highly +# maintainable. +# +# Variables are also supported when defined using :var=val. Variables may +# expand into ranges, 'cause they're awesome. Multiple variables may be +# delimited by semi-colons, as may multiple values. +# +# For example: +# :foo=1--3 +# $foo;7;9--10:$foo, 5--10,1/1/2017 +# +# Would generate: +# 1, 5, 1483246800 +# 1, 6, 1483246800 +# ... +# 5, 10, 1483246800 +# 2, 5, 1483246800 +# ... +# 9, 5, 14832468005 +# ... +# 1, 5, 1483246800 +# 1, 6, 1483246800 +# ... +## + + +function parseline( i, m, j, me, orig ) +{ + if ( i > NF ) + { + print + return + } + + orig = $i + + if ( match( $i, /^([0-9]+\/){2}[0-9]+$/, m ) ) + { + cmd = "date --date=" $i " +%s" + cmd |& getline $i + close(cmd) + } + + # check first for delimiters + if ( match( $i, /^([^;]+);(.*)$/, m ) ) + { + # give it a shot with the first value + $i = m[1] + parseline( i ) + + # strip off the first value and process with following value(s) + $i = m[2] + parseline( i ) + + # we've delegated; we're done + $i = orig + return + } + + # attempt to parse variable (may expand into a range) + if ( match( $i, /^\$([a-zA-Z_-]+)$/, m ) ) + { + $i = vars[ m[1] ]; + } + + # parse range + if ( match( $i, /^([0-9]+)--([0-9]+)$/, m ) ) + { + j = m[1] + me = m[2] + do + { + $i = j + parseline( i + 1 ) + } while ( j++ < me ) + } + else + { + parseline( i + 1 ); + } + + # restore to original value + $i = orig +} + + +BEGIN { + # we're parsing CSVs + FS = " *, *" + OFS = "," +} + + +# skip all lines that begin with `#', which denotes a comment, or are empty +/^#|^$/ { next; } + +# lines that begin with a colon are variable definitions +/^:/ { + match( $0, /^:([a-zA-Z_-]+)=(.*?)$/, m ) + vars[ m[1] ] = m[2] + next +} + +# lines that need any sort of processing (ranges, dates, etc) +/--|;|\$[a-zA-Z_-]|\// { parseline( 1 ); next; } + +# all other lines are normal; simply output them verbatim +{ + # this assignment will ensure that awk processes the output, ensuring that + # extra spaces between commas are stripped + $1=$1 + print +} |