# HG changeset patch # User František Kučera # Date 1557090560 -7200 # Node ID 46db0e6e548b475b6d149ff89c3f6195f7541cf6 # Parent efa96f51b308a336d3017253ae031cb5dad4dea7 pass name-value pair to AWK diff -r efa96f51b308 -r 46db0e6e548b src/AwkHandler.h --- a/src/AwkHandler.h Sun May 05 12:38:09 2019 +0200 +++ b/src/AwkHandler.h Sun May 05 23:09:20 2019 +0200 @@ -62,8 +62,11 @@ private: Configuration configuration; writer::RelationalWriter* relationalWriter; + std::wstring_convert> convertor; // TODO: support also other encodings int awkInputWriterFD = -1; + std::vector currentReaderMetadata; + integer_t currentAttributeIndex = 0; void createPipe(int& readerFD, int& writerFD) { int fds[2]; @@ -91,6 +94,21 @@ __pid_t waitResult2 = wait(NULL); awkInputWriterFD = -1; } + + currentAttributeIndex = 0; + currentReaderMetadata.clear(); + } + + string_t a2v(const string_t& attributeName) { + // FIXME: escape reserved names; prefix with _ ? + // cat awkgram.y | awk -v FS='\\{"|",' -v ORS='|' '/static const struct token tokentab/, /\};/ { if (/^\{/) { print $2} }' + // BEGIN|BEGINFILE|END|ENDFILE|adump|and|asort|asorti|atan2|bindtextdomain|break|case|close|compl|continue|cos|dcgettext|dcngettext|default|delete|do|else|eval|exit|exp|fflush|for|func|function|gensub|getline|gsub|if|in|include|index|int|intdiv0|isarray|length|load|log|lshift|match|mktime|namespace|next|nextfile|or|patsplit|print|printf|rand|return|rshift|sin|split|sprintf|sqrt|srand|stopme|strftime|strtonum|sub|substr|switch|system|systime|tolower|toupper|typeof|while|xor + return attributeName; + } + + string_t escapeAwkValue(const string_t& value) { + // FIXME: escape field and record separators + return value; } public: @@ -101,6 +119,7 @@ void startRelation(string_t name, vector attributes) override { cleanUp(); + currentReaderMetadata = attributes; int awkInputReaderFD; int awkOutputReaderFD; @@ -122,7 +141,7 @@ redirectFD(awkOutputWriterFD, STDOUT_FILENO); // Runs AWK program found on $PATH → user can plug-in a custom implementation or a wrapper, but this can be also bit dangerous (however AWK itself is dangerous). - execlp("awk", "awk", "{print \"AWK says: line \" NR \" = \" $0;}", nullptr); + execlp("awk", "awk", "BEGIN { FS=\"\\t\" }; {print \"AWK says: line \" NR \" '\" $0 \"' has \" NF \" fields; first field is '\" $1 \"'\";}", nullptr); } else { // Parent process closeOrThrow(awkInputReaderFD); @@ -158,7 +177,20 @@ } void attribute(const string_t& value) override { - dprintf(awkInputWriterFD, "attribute!\n"); + string_t variableName = a2v(currentReaderMetadata[currentAttributeIndex].getAttributeName()); + string_t variableValue = escapeAwkValue(value); + + currentAttributeIndex++; + currentAttributeIndex = currentAttributeIndex % currentReaderMetadata.size(); + + // TODO: just the value – move name to the AWK function + std::string variablePair = convertor.to_bytes(variableName + L"=" + variableValue); + + if (currentAttributeIndex == 0) variablePair += "\n"; + else variablePair += "\t"; + + write(awkInputWriterFD, variablePair.c_str(), variablePair.length()); + } void endOfPipe() {