67 std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings |
67 std::wstring_convert<codecvt_utf8<wchar_t>> convertor; // TODO: support also other encodings |
68 |
68 |
69 int awkInputWriterFD = -1; |
69 int awkInputWriterFD = -1; |
70 RelationConfiguration* currentRelationConfiguration = nullptr; |
70 RelationConfiguration* currentRelationConfiguration = nullptr; |
71 std::vector<AttributeMetadata> currentReaderMetadata; |
71 std::vector<AttributeMetadata> currentReaderMetadata; |
72 vector<writer::AttributeMetadata> currentWriterMetadata; |
72 std::vector<writer::AttributeMetadata> currentWriterMetadata; |
|
73 std::map<string_t, string_t> currenVariablesMapping; |
73 integer_t currentAttributeIndex = 0; |
74 integer_t currentAttributeIndex = 0; |
74 |
75 |
75 void createPipe(int& readerFD, int& writerFD) { |
76 void createPipe(int& readerFD, int& writerFD) { |
76 int fds[2]; |
77 int fds[2]; |
77 int result = pipe(fds); |
78 int result = pipe(fds); |
139 } |
140 } |
140 |
141 |
141 currentAttributeIndex = 0; |
142 currentAttributeIndex = 0; |
142 currentReaderMetadata.clear(); |
143 currentReaderMetadata.clear(); |
143 currentWriterMetadata.clear(); |
144 currentWriterMetadata.clear(); |
|
145 currenVariablesMapping.clear(); |
144 currentRelationConfiguration = nullptr; |
146 currentRelationConfiguration = nullptr; |
145 } |
147 } |
146 |
148 |
|
149 void generateVariableMappings() { |
|
150 for (AttributeMetadata m : currentReaderMetadata) currenVariablesMapping[m.getAttributeName()] = L""; |
|
151 for (writer::AttributeMetadata m : currentWriterMetadata) currenVariablesMapping[m.attributeName] = L""; |
|
152 for (DefinitionRecipe d : configuration.definitions) currenVariablesMapping[d.name] = L""; |
|
153 for (DefinitionRecipe d : currentRelationConfiguration->definitions) currenVariablesMapping[d.name] = L""; |
|
154 |
|
155 for (std::pair<string_t, string_t> m : currenVariablesMapping) { |
|
156 currenVariablesMapping[m.first] = escapeAwkVariableName(m.first); |
|
157 } |
|
158 } |
|
159 |
147 string_t a2v(const string_t& attributeName) { |
160 string_t a2v(const string_t& attributeName) { |
|
161 if (currenVariablesMapping.find(attributeName) != currenVariablesMapping.end()) return currenVariablesMapping[attributeName]; |
|
162 else throw cli::RelpipeCLIException(L"Unable to find value in currenVariablesMapping", cli::CLI::EXIT_CODE_UNEXPECTED_ERROR); // TODO: better exceptions? |
|
163 } |
|
164 |
|
165 template <typename K, typename V> bool containsValue(std::map<K, V> map, V value) { |
|
166 for (std::pair<K, V> p : map) if (p.second == value) return true; |
|
167 return false; |
|
168 } |
|
169 |
|
170 string_t escapeAwkVariableName(const string_t& attributeName) { |
148 // cat awkgram.y | awk -v FS='\\{"|",' -v ORS='|' '/static const struct token tokentab/, /\};/ { if (/^\{/) { print $2} }' |
171 // cat awkgram.y | awk -v FS='\\{"|",' -v ORS='|' '/static const struct token tokentab/, /\};/ { if (/^\{/) { print $2} }' |
|
172 // cat AwkHandler.h | awk -v FS=' |\\(' -v ORS='|' '/awkScript.*"function/ { print $4; }' |
149 std::wregex awkReservedNames(L"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"); |
173 std::wregex awkReservedNames(L"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"); |
150 std::wregex trReservedNames(L"_escape|_unescape|_readVariables|_writeVariables|record"); |
174 std::wregex trReservedNames(L"_escape|_unescape|_readVariables|_writeVariables|record"); |
151 if (regex_match(attributeName, awkReservedNames) || regex_match(attributeName, trReservedNames)) return a2v(L"_" + attributeName); |
175 std::wregex badCharacters(L"[^a-zA-Z0-9_]|^([0-9])"); |
152 else return attributeName; |
176 |
|
177 const string_t& name = std::regex_replace(attributeName, badCharacters, L"_$1"); |
|
178 |
|
179 bool badName = false; |
|
180 badName |= regex_match(name, awkReservedNames); |
|
181 badName |= regex_match(name, trReservedNames); |
|
182 badName |= containsValue(currenVariablesMapping, name); |
|
183 |
|
184 if (badName) return escapeAwkVariableName(L"_" + name); |
|
185 else return name; |
153 } |
186 } |
154 |
187 |
155 string_t escapeAwkValue(const string_t& value) { |
188 string_t escapeAwkValue(const string_t& value) { |
156 std::wstringstream escaped; |
189 std::wstringstream escaped; |
157 for (wchar_t ch : value) { |
190 for (wchar_t ch : value) { |
226 } else { |
259 } else { |
227 add(currentReaderMetadata, currentWriterMetadata); |
260 add(currentReaderMetadata, currentWriterMetadata); |
228 } |
261 } |
229 |
262 |
230 if (currentRelationConfiguration) { |
263 if (currentRelationConfiguration) { |
|
264 generateVariableMappings(); |
|
265 |
231 int awkInputReaderFD; |
266 int awkInputReaderFD; |
232 int awkOutputReaderFD; |
267 int awkOutputReaderFD; |
233 int awkOutputWriterFD; |
268 int awkOutputWriterFD; |
234 |
269 |
235 createPipe(awkInputReaderFD, awkInputWriterFD); |
270 createPipe(awkInputReaderFD, awkInputWriterFD); |