1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4 #include <ctype.h> // for tolower(), toupper()
5 #include "lib/mlr_globals.h"
6 #include "lib/mlrutil.h"
7 #include "lib/mlrregex.h"
8 #include "lib/mtrand.h"
9 #include "mapping/mapper.h"
10 #include "dsl/rval_evaluators.h"
11 #include "dsl/rxval_evaluators.h" // For indexed-function-call feature
12 #include "dsl/function_manager.h"
13 #include "dsl/context_flags.h"
14 
15 // ================================================================
16 // See comments in rval_evaluators.h
17 // ================================================================
18 
19 // ================================================================
20 // The grammar permits certain statements which are syntactically invalid, (a) because it's awkward to handle
21 // there, and (b) because we get far better control over error messages here (vs. 'syntax error').
22 // The context flags are used as the CST is built from the AST, for CST-build-time validation.
23 // This semantic analysis isn't a separate pass through the AST or CST since it's done while the
24 // CST is being constructed.
25 
rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)26 rval_evaluator_t* rval_evaluator_alloc_from_ast(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
27 	int type_inferencing, int context_flags)
28 {
29 	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
30 	if (pnode->pchildren == NULL) {
31 		// leaf node
32 		switch(pnode->type) {
33 
34 		case MD_AST_NODE_TYPE_FIELD_NAME:
35 			if (context_flags & IN_BEGIN_OR_END) {
36 				fprintf(stderr, "%s: statements involving $-variables are not valid within begin or end blocks.\n",
37 					MLR_GLOBALS.bargv0);
38 				exit(1);
39 			}
40 			return rval_evaluator_alloc_from_field_name(pnode->text, type_inferencing);
41 			break;
42 
43 		case MD_AST_NODE_TYPE_STRING_LITERAL:
44 			// In input data such as echo x=3,y=4 | mlr put '$z=$x+$y', the 3 and 4 are strings
45 			// which need parsing as integers. But in DSL expression literals such as 'put $z = "3" + 4'
46 			// the "3" should not.
47 			return rval_evaluator_alloc_from_string_literal(pnode->text);
48 			break;
49 
50 		case MD_AST_NODE_TYPE_NUMERIC_LITERAL:
51 			// In input data such as echo x=3,y=4 | mlr put '$z=$x+$y', the 3 and 4 are strings
52 			// which need parsing as integers. But in DSL expression literals such as 'put $z = "3" + 4'
53 			// the "3" should not.
54 			return rval_evaluator_alloc_from_numeric_literal(pnode->text);
55 			break;
56 
57 		case MD_AST_NODE_TYPE_BOOLEAN_LITERAL:
58 			return rval_evaluator_alloc_from_boolean_literal(pnode->text);
59 			break;
60 
61 		case MD_AST_NODE_TYPE_REGEXI:
62 			return rval_evaluator_alloc_from_string_literal(pnode->text);
63 			break;
64 
65 		case MD_AST_NODE_TYPE_CONTEXT_VARIABLE:
66 			return rval_evaluator_alloc_from_context_variable(pnode->text);
67 			break;
68 
69 		case MD_AST_NODE_TYPE_NONINDEXED_LOCAL_VARIABLE:
70 			return rval_evaluator_alloc_from_local_variable(pnode->vardef_frame_relative_index);
71 			break;
72 
73 		case MD_AST_NODE_TYPE_FULL_SREC:
74 			fprintf(stderr, "%s: $* is not valid within scalar contexts.\n",
75 				MLR_GLOBALS.bargv0);
76 			exit(1);
77 
78 		case MD_AST_NODE_TYPE_FULL_OOSVAR:
79 			fprintf(stderr, "%s: @* is not valid within scalar contexts.\n",
80 				MLR_GLOBALS.bargv0);
81 			exit(1);
82 
83 		case MD_AST_NODE_TYPE_MAP_LITERAL:
84 			fprintf(stderr, "%s: map-literals are not valid within scalar contexts.\n",
85 				MLR_GLOBALS.bargv0);
86 			exit(1);
87 
88 		default:
89 			MLR_INTERNAL_CODING_ERROR();
90 			return NULL; // not reached
91 			break;
92 		}
93 
94 	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
95 	} else if (pnode->type == MD_AST_NODE_TYPE_INDIRECT_FIELD_NAME) {
96 		if (context_flags & IN_BEGIN_OR_END) {
97 			fprintf(stderr, "%s: statements involving $-variables are not valid within begin or end blocks.\n",
98 				MLR_GLOBALS.bargv0);
99 			exit(1);
100 		}
101 		return rval_evaluator_alloc_from_indirect_field_name(pnode->pchildren->phead->pvvalue, pfmgr,
102 			type_inferencing, context_flags);
103 
104 	} else if (pnode->type == MD_AST_NODE_TYPE_POSITIONAL_SREC_NAME) {
105 		if (context_flags & IN_BEGIN_OR_END) {
106 			fprintf(stderr, "%s: statements involving $-variables are not valid within begin or end blocks.\n",
107 				MLR_GLOBALS.bargv0);
108 			exit(1);
109 		}
110 		return rval_evaluator_alloc_from_positional_srec_field_name(pnode->pchildren->phead->pvvalue, pfmgr,
111 			type_inferencing, context_flags);
112 
113 	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
114 	} else if (pnode->type == MD_AST_NODE_TYPE_OOSVAR_KEYLIST) {
115 		return rval_evaluator_alloc_from_oosvar_keylist(pnode, pfmgr, type_inferencing, context_flags);
116 
117 	} else if (pnode->type == MD_AST_NODE_TYPE_INDEXED_LOCAL_VARIABLE) {
118 		return rval_evaluator_alloc_from_local_map_keylist(pnode, pfmgr, type_inferencing, context_flags);
119 
120 	} else if (pnode->type == MD_AST_NODE_TYPE_INDEXED_FUNCTION_CALLSITE) {
121 		return rval_evaluator_alloc_from_indexed_function_call(pnode, pfmgr, type_inferencing, context_flags);
122 
123 	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
124 	} else if (pnode->type == MD_AST_NODE_TYPE_ENV) {
125 		return rval_evaluator_alloc_from_environment(pnode, pfmgr, type_inferencing, context_flags);
126 
127 	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
128 	} else if ((pnode->type == MD_AST_NODE_TYPE_FUNCTION_CALLSITE) || (pnode->type == MD_AST_NODE_TYPE_OPERATOR)) {
129 		return fmgr_alloc_provisional_from_operator_or_function_call(pfmgr, pnode, type_inferencing, context_flags);
130 
131 	} else if (pnode->type == MD_AST_NODE_TYPE_FULL_SREC) {
132 		fprintf(stderr, "%s: $* is not valid within scalar contexts.\n",
133 			MLR_GLOBALS.bargv0);
134 		exit(1);
135 
136 	} else if (pnode->type == MD_AST_NODE_TYPE_FULL_OOSVAR) {
137 		fprintf(stderr, "%s: @* is not valid within scalar contexts.\n",
138 			MLR_GLOBALS.bargv0);
139 		exit(1);
140 
141 	} else if (pnode->type == MD_AST_NODE_TYPE_MAP_LITERAL) {
142 		fprintf(stderr, "%s: map-literals are not valid within scalar contexts.\n",
143 			MLR_GLOBALS.bargv0);
144 		exit(1);
145 
146 	//  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
147 	// This is the fall-through which typically gets hit when you update the AST-producing grammar but
148 	// haven't yet implemented the CST handler for it.
149 	} else {
150 		MLR_INTERNAL_CODING_ERROR();
151 		return NULL; // not reached
152 	}
153 }
154 
155 // ================================================================
156 typedef struct _rval_evaluator_field_name_state_t {
157 	char* field_name;
158 } rval_evaluator_field_name_state_t;
159 
rval_evaluator_field_name_func_string_only(void * pvstate,variables_t * pvars)160 static mv_t rval_evaluator_field_name_func_string_only(void* pvstate, variables_t* pvars) {
161 	rval_evaluator_field_name_state_t* pstate = pvstate;
162 	return get_srec_value_string_only(pstate->field_name, pvars->pinrec, pvars->ptyped_overlay);
163 }
164 
rval_evaluator_field_name_func_string_float(void * pvstate,variables_t * pvars)165 static mv_t rval_evaluator_field_name_func_string_float(void* pvstate, variables_t* pvars) {
166 	rval_evaluator_field_name_state_t* pstate = pvstate;
167 	return get_srec_value_string_float(pstate->field_name, pvars->pinrec, pvars->ptyped_overlay);
168 }
169 
rval_evaluator_field_name_func_string_float_int(void * pvstate,variables_t * pvars)170 static mv_t rval_evaluator_field_name_func_string_float_int(void* pvstate, variables_t* pvars) {
171 	rval_evaluator_field_name_state_t* pstate = pvstate;
172 	return get_srec_value_string_float_int(pstate->field_name, pvars->pinrec, pvars->ptyped_overlay);
173 }
174 
rval_evaluator_field_name_free(rval_evaluator_t * pevaluator)175 static void rval_evaluator_field_name_free(rval_evaluator_t* pevaluator) {
176 	rval_evaluator_field_name_state_t* pstate = pevaluator->pvstate;
177 	free(pstate->field_name);
178 	free(pstate);
179 	free(pevaluator);
180 }
181 
rval_evaluator_alloc_from_field_name(char * field_name,int type_inferencing)182 rval_evaluator_t* rval_evaluator_alloc_from_field_name(char* field_name, int type_inferencing) {
183 	rval_evaluator_field_name_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_field_name_state_t));
184 	pstate->field_name = mlr_strdup_or_die(field_name);
185 
186 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
187 	pevaluator->pvstate = pstate;
188 	pevaluator->pprocess_func = NULL;
189 	switch (type_inferencing) {
190 	case TYPE_INFER_STRING_ONLY:
191 		pevaluator->pprocess_func = rval_evaluator_field_name_func_string_only;
192 		break;
193 	case TYPE_INFER_STRING_FLOAT:
194 		pevaluator->pprocess_func = rval_evaluator_field_name_func_string_float;
195 		break;
196 	case TYPE_INFER_STRING_FLOAT_INT:
197 		pevaluator->pprocess_func = rval_evaluator_field_name_func_string_float_int;
198 		break;
199 	default:
200 		MLR_INTERNAL_CODING_ERROR();
201 		break;
202 	}
203 	pevaluator->pfree_func = rval_evaluator_field_name_free;
204 
205 	return pevaluator;
206 }
207 
208 // ================================================================
209 typedef struct _rval_evaluator_indirect_field_name_state_t {
210 	rval_evaluator_t* pname_evaluator;
211 } rval_evaluator_indirect_field_name_state_t;
212 
rval_evaluator_indirect_field_name_func_string_only(void * pvstate,variables_t * pvars)213 static mv_t rval_evaluator_indirect_field_name_func_string_only(void* pvstate, variables_t* pvars) {
214 	rval_evaluator_indirect_field_name_state_t* pstate = pvstate;
215 
216 	mv_t mvname = pstate->pname_evaluator->pprocess_func(pstate->pname_evaluator->pvstate, pvars);
217 	if (mv_is_null(&mvname)) {
218 		mv_free(&mvname);
219 		return mv_absent();
220 	}
221 	char free_flags = NO_FREE;
222 	char* indirect_field_name = mv_maybe_alloc_format_val(&mvname, &free_flags);
223 
224 	mv_t rv = get_srec_value_string_only(indirect_field_name, pvars->pinrec, pvars->ptyped_overlay);
225 	if (free_flags & FREE_ENTRY_VALUE)
226 		free(indirect_field_name);
227 	mv_free(&mvname);
228 	return rv;
229 }
230 
rval_evaluator_indirect_field_name_func_string_float(void * pvstate,variables_t * pvars)231 static mv_t rval_evaluator_indirect_field_name_func_string_float(void* pvstate, variables_t* pvars) {
232 	rval_evaluator_indirect_field_name_state_t* pstate = pvstate;
233 
234 	mv_t mvname = pstate->pname_evaluator->pprocess_func(pstate->pname_evaluator->pvstate, pvars);
235 	if (mv_is_null(&mvname)) {
236 		mv_free(&mvname);
237 		return mv_absent();
238 	}
239 	char free_flags = NO_FREE;
240 	char* indirect_field_name = mv_maybe_alloc_format_val(&mvname, &free_flags);
241 
242 	mv_t rv = get_srec_value_string_float(indirect_field_name, pvars->pinrec, pvars->ptyped_overlay);
243 
244 	if (free_flags & FREE_ENTRY_VALUE)
245 		free(indirect_field_name);
246 	mv_free(&mvname);
247 	return rv;
248 }
249 
rval_evaluator_indirect_field_name_func_string_float_int(void * pvstate,variables_t * pvars)250 static mv_t rval_evaluator_indirect_field_name_func_string_float_int(void* pvstate, variables_t* pvars) {
251 	rval_evaluator_indirect_field_name_state_t* pstate = pvstate;
252 
253 	mv_t mvname = pstate->pname_evaluator->pprocess_func(pstate->pname_evaluator->pvstate, pvars);
254 	if (mv_is_null(&mvname)) {
255 		mv_free(&mvname);
256 		return mv_absent();
257 	}
258 	char free_flags = NO_FREE;
259 	char* indirect_field_name = mv_maybe_alloc_format_val(&mvname, &free_flags);
260 
261 	mv_t rv = get_srec_value_string_float_int(indirect_field_name, pvars->pinrec, pvars->ptyped_overlay);
262 
263 	if (free_flags & FREE_ENTRY_VALUE)
264 		free(indirect_field_name);
265 	mv_free(&mvname);
266 	return rv;
267 }
268 
rval_evaluator_indirect_field_name_free(rval_evaluator_t * pevaluator)269 static void rval_evaluator_indirect_field_name_free(rval_evaluator_t* pevaluator) {
270 	rval_evaluator_indirect_field_name_state_t* pstate = pevaluator->pvstate;
271 	pstate->pname_evaluator->pfree_func(pstate->pname_evaluator);
272 	free(pstate);
273 	free(pevaluator);
274 }
275 
rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node_t * pnamenode,fmgr_t * pfmgr,int type_inferencing,int context_flags)276 rval_evaluator_t* rval_evaluator_alloc_from_indirect_field_name(mlr_dsl_ast_node_t* pnamenode, fmgr_t* pfmgr,
277 	int type_inferencing, int context_flags)
278 {
279 	rval_evaluator_indirect_field_name_state_t* pstate = mlr_malloc_or_die(
280 		sizeof(rval_evaluator_indirect_field_name_state_t));
281 
282 	pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, pfmgr, type_inferencing, context_flags);
283 
284 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
285 	pevaluator->pvstate = pstate;
286 	pevaluator->pprocess_func = NULL;
287 	switch (type_inferencing) {
288 	case TYPE_INFER_STRING_ONLY:
289 		pevaluator->pprocess_func = rval_evaluator_indirect_field_name_func_string_only;
290 		break;
291 	case TYPE_INFER_STRING_FLOAT:
292 		pevaluator->pprocess_func = rval_evaluator_indirect_field_name_func_string_float;
293 		break;
294 	case TYPE_INFER_STRING_FLOAT_INT:
295 		pevaluator->pprocess_func = rval_evaluator_indirect_field_name_func_string_float_int;
296 		break;
297 	default:
298 		MLR_INTERNAL_CODING_ERROR();
299 		break;
300 	}
301 	pevaluator->pfree_func = rval_evaluator_indirect_field_name_free;
302 
303 	return pevaluator;
304 }
305 
306 // ================================================================
307 typedef struct _rval_evaluator_positional_field_name_state_t {
308 	rval_evaluator_t* pname_evaluator;
309 } rval_evaluator_positional_field_name_state_t;
310 
rval_evaluator_positional_field_name_func(void * pvstate,variables_t * pvars)311 static mv_t rval_evaluator_positional_field_name_func(void* pvstate, variables_t* pvars) {
312 	rval_evaluator_positional_field_name_state_t* pstate = pvstate;
313 
314 	mv_t mvname = pstate->pname_evaluator->pprocess_func(pstate->pname_evaluator->pvstate, pvars);
315 	if (mv_is_null(&mvname)) {
316 		mv_free(&mvname);
317 		return mv_absent();
318 	}
319 	if (!mv_is_int(&mvname)) {
320 		char free_flags = NO_FREE;
321 		char* text = mv_maybe_alloc_format_val(&mvname, &free_flags);
322 		fprintf(stderr, "%s: positional names must be integers; got \"%s\".\n", MLR_GLOBALS.bargv0, text);
323 		if (free_flags)
324 			free(text);
325 		exit(1);
326 	}
327 	int positional_field_name = mvname.u.intv;
328 
329 	char* key = lrec_get_key_by_position(pvars->pinrec, positional_field_name);
330 	mv_t rv = mv_absent();
331 	if (key != NULL) {
332 		rv = mv_from_string_with_free(mlr_strdup_or_die(key));
333 	}
334 	mv_free(&mvname);
335 
336 	return rv;
337 }
338 
rval_evaluator_positional_field_name_free(rval_evaluator_t * pevaluator)339 static void rval_evaluator_positional_field_name_free(rval_evaluator_t* pevaluator) {
340 	rval_evaluator_positional_field_name_state_t* pstate = pevaluator->pvstate;
341 	pstate->pname_evaluator->pfree_func(pstate->pname_evaluator);
342 	free(pstate);
343 	free(pevaluator);
344 }
345 
rval_evaluator_alloc_from_positional_srec_field_name(mlr_dsl_ast_node_t * pnamenode,fmgr_t * pfmgr,int type_inferencing,int context_flags)346 rval_evaluator_t* rval_evaluator_alloc_from_positional_srec_field_name(mlr_dsl_ast_node_t* pnamenode, fmgr_t* pfmgr,
347 	int type_inferencing, int context_flags)
348 {
349 	rval_evaluator_positional_field_name_state_t* pstate = mlr_malloc_or_die(
350 		sizeof(rval_evaluator_positional_field_name_state_t));
351 
352 	pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, pfmgr, type_inferencing, context_flags);
353 
354 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
355 	pevaluator->pvstate = pstate;
356 	pevaluator->pprocess_func = rval_evaluator_positional_field_name_func;
357 	pevaluator->pfree_func = rval_evaluator_positional_field_name_free;
358 
359 	return pevaluator;
360 }
361 
362 // ================================================================
363 typedef struct _rval_evaluator_oosvar_keylist_state_t {
364 	sllv_t* poosvar_rhs_keylist_evaluators;
365 } rval_evaluator_oosvar_keylist_state_t;
366 
rval_evaluator_oosvar_keylist_func(void * pvstate,variables_t * pvars)367 mv_t rval_evaluator_oosvar_keylist_func(void* pvstate, variables_t* pvars) {
368 	rval_evaluator_oosvar_keylist_state_t* pstate = pvstate;
369 
370 	int all_non_null_or_error = TRUE;
371 	sllmv_t* pmvkeys = evaluate_list(pstate->poosvar_rhs_keylist_evaluators, pvars, &all_non_null_or_error);
372 
373 	mv_t rv = mv_absent();
374 	if (all_non_null_or_error) {
375 		int error = 0;
376 		mv_t* pval = mlhmmv_root_look_up_and_ref_terminal(pvars->poosvars, pmvkeys, &error);
377 		if (pval != NULL) {
378 			if (pval->type == MT_STRING && *pval->u.strv == 0)
379 				rv = mv_empty();
380 			else
381 				rv = mv_copy(pval);
382 		}
383 	}
384 
385 	sllmv_free(pmvkeys);
386 	return rv;
387 }
388 
rval_evaluator_oosvar_keylist_free(rval_evaluator_t * pevaluator)389 static void rval_evaluator_oosvar_keylist_free(rval_evaluator_t* pevaluator) {
390 	rval_evaluator_oosvar_keylist_state_t* pstate = pevaluator->pvstate;
391 	for (sllve_t* pe = pstate->poosvar_rhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
392 		rval_evaluator_t* pevaluator = pe->pvvalue;
393 		pevaluator->pfree_func(pevaluator);
394 	}
395 	sllv_free(pstate->poosvar_rhs_keylist_evaluators);
396 	free(pstate);
397 	free(pevaluator);
398 }
399 
400 // Example AST:
401 //
402 // $ mlr -n put -v '$y = @x[1]["two"][$3+4][@5]'
403 // list (statement_list):
404 //     = (srec_assignment):
405 //         y (field_name).
406 //         oosvar_keylist (oosvar_keylist):
407 //             x (string_literal).
408 //             1 (numeric_literal).
409 //             two (numeric_literal).
410 //             + (operator):
411 //                 3 (field_name).
412 //                 4 (numeric_literal).
413 //             oosvar_keylist (oosvar_keylist):
414 //                 5 (string_literal).
415 
rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)416 rval_evaluator_t* rval_evaluator_alloc_from_oosvar_keylist(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
417 	int type_inferencing, int context_flags)
418 {
419 	rval_evaluator_oosvar_keylist_state_t* pstate = mlr_malloc_or_die(
420 		sizeof(rval_evaluator_oosvar_keylist_state_t));
421 
422 	sllv_t* pkeylist_evaluators = sllv_alloc();
423 
424 	for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
425 		mlr_dsl_ast_node_t* pkeynode = pe->pvvalue;
426 		if (pkeynode->type == MD_AST_NODE_TYPE_STRING_LITERAL) {
427 			sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_string(pkeynode->text));
428 		} else {
429 			sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, pfmgr,
430 				type_inferencing, context_flags));
431 		}
432 	}
433 	pstate->poosvar_rhs_keylist_evaluators = pkeylist_evaluators;
434 
435 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
436 	pevaluator->pvstate = pstate;
437 	pevaluator->pprocess_func = NULL;
438 	pevaluator->pprocess_func = rval_evaluator_oosvar_keylist_func;
439 	pevaluator->pfree_func = rval_evaluator_oosvar_keylist_free;
440 
441 	return pevaluator;
442 }
443 
444 // ================================================================
445 typedef struct _rval_evaluator_local_map_keylist_state_t {
446 	int vardef_frame_relative_index;
447 	sllv_t* plocal_map_rhs_keylist_evaluators;
448 } rval_evaluator_local_map_keylist_state_t;
449 
rval_evaluator_local_map_keylist_func(void * pvstate,variables_t * pvars)450 mv_t rval_evaluator_local_map_keylist_func(void* pvstate, variables_t* pvars) {
451 	rval_evaluator_local_map_keylist_state_t* pstate = pvstate;
452 
453 	int all_non_null_or_error = TRUE;
454 	sllmv_t* pmvkeys = evaluate_list(pstate->plocal_map_rhs_keylist_evaluators, pvars, &all_non_null_or_error);
455 
456 	mv_t rv = mv_absent();
457 	if (all_non_null_or_error) {
458 		local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
459 		mv_t val = local_stack_frame_ref_terminal_from_indexed(pframe, pstate->vardef_frame_relative_index, pmvkeys);
460 		if (val.type == MT_STRING && *val.u.strv == 0)
461 			rv = mv_empty();
462 		else
463 			rv = mv_copy(&val);
464 	}
465 
466 	sllmv_free(pmvkeys);
467 	return rv;
468 }
469 
rval_evaluator_local_map_keylist_free(rval_evaluator_t * pevaluator)470 static void rval_evaluator_local_map_keylist_free(rval_evaluator_t* pevaluator) {
471 	rval_evaluator_local_map_keylist_state_t* pstate = pevaluator->pvstate;
472 	for (sllve_t* pe = pstate->plocal_map_rhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) {
473 		rval_evaluator_t* pevaluator = pe->pvvalue;
474 		pevaluator->pfree_func(pevaluator);
475 	}
476 	sllv_free(pstate->plocal_map_rhs_keylist_evaluators);
477 	free(pstate);
478 	free(pevaluator);
479 }
480 
rval_evaluator_alloc_from_local_map_keylist(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)481 rval_evaluator_t* rval_evaluator_alloc_from_local_map_keylist(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
482 	int type_inferencing, int context_flags)
483 {
484 	rval_evaluator_local_map_keylist_state_t* pstate = mlr_malloc_or_die(
485 		sizeof(rval_evaluator_local_map_keylist_state_t));
486 
487 	MLR_INTERNAL_CODING_ERROR_IF(pnode->vardef_frame_relative_index == MD_UNUSED_INDEX);
488 
489 	pstate->vardef_frame_relative_index = pnode->vardef_frame_relative_index;
490 
491 	sllv_t* pkeylist_evaluators = sllv_alloc();
492 	for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) {
493 		mlr_dsl_ast_node_t* pkeynode = pe->pvvalue;
494 		if (pkeynode->type == MD_AST_NODE_TYPE_STRING_LITERAL) {
495 			sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_string(pkeynode->text));
496 		} else {
497 			sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, pfmgr,
498 				type_inferencing, context_flags));
499 		}
500 	}
501 	pstate->plocal_map_rhs_keylist_evaluators = pkeylist_evaluators;
502 
503 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
504 	pevaluator->pvstate = pstate;
505 	pevaluator->pprocess_func = NULL;
506 	pevaluator->pprocess_func = rval_evaluator_local_map_keylist_func;
507 	pevaluator->pfree_func = rval_evaluator_local_map_keylist_free;
508 
509 	return pevaluator;
510 }
511 
512 // ================================================================
513 // This is used for evaluating numbers in literal expressions, e.g. '$x = 4'
514 
515 typedef struct _rval_evaluator_numeric_literal_state_t {
516 	mv_t literal;
517 } rval_evaluator_numeric_literal_state_t;
518 
rval_evaluator_non_string_literal_func(void * pvstate,variables_t * pvars)519 mv_t rval_evaluator_non_string_literal_func(void* pvstate, variables_t* pvars) {
520 	rval_evaluator_numeric_literal_state_t* pstate = pvstate;
521 	return pstate->literal;
522 }
523 
rval_evaluator_string_literal_func(void * pvstate,variables_t * pvars)524 mv_t rval_evaluator_string_literal_func(void* pvstate, variables_t* pvars) {
525 	rval_evaluator_numeric_literal_state_t* pstate = pvstate;
526 	char* input = pstate->literal.u.strv;
527 
528 	if (pvars->ppregex_captures == NULL || *pvars->ppregex_captures == NULL) {
529 		return mv_from_string_no_free(input);
530 	} else {
531 		int was_allocated = FALSE;
532 		char* output = interpolate_regex_captures(input, *pvars->ppregex_captures, &was_allocated);
533 		if (was_allocated)
534 			return mv_from_string_with_free(output);
535 		else
536 			return mv_from_string_no_free(output);
537 	}
538 }
rval_evaluator_numeric_literal_free(rval_evaluator_t * pevaluator)539 static void rval_evaluator_numeric_literal_free(rval_evaluator_t* pevaluator) {
540 	rval_evaluator_numeric_literal_state_t* pstate = pevaluator->pvstate;
541 	mv_free(&pstate->literal);
542 	free(pstate);
543 	free(pevaluator);
544 }
545 
546 // How to handle echo a=1,b=2.0 | mlr put {flag} '$s = $a; $t = $b; $u = 3; $v = 4.0', where {flag} is -S, -F, or
547 // neither:
548 // * (no flag) TYPE_INFER_STRING_FLOAT_INT: a and s = int 1,      b and t = float 2.0,    u = int 3, v = float 4.0
549 // * (-F flag) TYPE_INFER_STRING_FLOAT:     a and s = float 1.0,  b and t = float 2.0,    u = int 3, v = float 4.0
550 // * (-S flag) TYPE_INFER_STRING_ONLY:      a and s = string "1", b and t = string "2.0", u = int 3, v = float 4.0
551 // The -S/-F flags for put/filter are for type inferencing in record data, not in literal expressions.
552 
rval_evaluator_alloc_from_numeric_literal(char * string)553 rval_evaluator_t* rval_evaluator_alloc_from_numeric_literal(char* string) {
554 	rval_evaluator_numeric_literal_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_numeric_literal_state_t));
555 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
556 
557 	if (string == NULL) {
558 		pstate->literal = mv_absent();
559 		pevaluator->pprocess_func = rval_evaluator_non_string_literal_func;
560 	} else {
561 		long long intv;
562 		double fltv;
563 
564 		pevaluator->pprocess_func = NULL;
565 
566 		if (mlr_try_int_from_string(string, &intv)) {
567 			pstate->literal = mv_from_int(intv);
568 			pevaluator->pprocess_func = rval_evaluator_non_string_literal_func;
569 		} else if (mlr_try_float_from_string(string, &fltv)) {
570 			pstate->literal = mv_from_float(fltv);
571 			pevaluator->pprocess_func = rval_evaluator_non_string_literal_func;
572 		} else {
573 			pstate->literal = mv_from_string_no_free(string);
574 			pevaluator->pprocess_func = rval_evaluator_string_literal_func;
575 		}
576 	}
577 	pevaluator->pfree_func = rval_evaluator_numeric_literal_free;
578 
579 	pevaluator->pvstate = pstate;
580 	return pevaluator;
581 }
582 
583 // ================================================================
584 // This is used for evaluating strings and numbers in literal expressions, e.g. '$x = "abc"'
585 // or '$x = "left_\1". The values are subject to replacement with regex captures. See comments
586 // in mapper_put for more information.
587 //
588 // Compare rval_evaluator_alloc_from_string which doesn't do regex replacement: it is intended for
589 // oosvar names on expression left-hand sides (outside of this file).
590 
591 typedef struct _rval_evaluator_string_literal_state_t {
592 	mv_t literal;
593 } rval_evaluator_string_literal_state_t;
594 
rval_evaluator_string_literal_free(rval_evaluator_t * pevaluator)595 static void rval_evaluator_string_literal_free(rval_evaluator_t* pevaluator) {
596 	rval_evaluator_string_literal_state_t* pstate = pevaluator->pvstate;
597 	mv_free(&pstate->literal);
598 	free(pstate);
599 	free(pevaluator);
600 }
601 
rval_evaluator_alloc_from_string_literal(char * string)602 rval_evaluator_t* rval_evaluator_alloc_from_string_literal(char* string) {
603 	rval_evaluator_string_literal_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_string_literal_state_t));
604 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
605 
606 	if (string == NULL) {
607 		pstate->literal = mv_absent();
608 		pevaluator->pprocess_func = rval_evaluator_non_string_literal_func;
609 	} else {
610 		pstate->literal = mv_from_string_no_free(string);
611 		pevaluator->pprocess_func = rval_evaluator_string_literal_func;
612 	}
613 	pevaluator->pfree_func = rval_evaluator_string_literal_free;
614 
615 	pevaluator->pvstate = pstate;
616 	return pevaluator;
617 }
618 
619 // ================================================================
620 // This is intended only for oosvar names on expression left-hand sides (outside of this file).
621 // Compare rval_evaluator_alloc_from_string_literal.
622 
623 typedef struct _rval_evaluator_string_state_t {
624 	char* string;
625 } rval_evaluator_string_state_t;
626 
rval_evaluator_string_func(void * pvstate,variables_t * pvars)627 mv_t rval_evaluator_string_func(void* pvstate, variables_t* pvars) {
628 	rval_evaluator_string_state_t* pstate = pvstate;
629 	return mv_from_string_no_free(pstate->string);
630 }
rval_evaluator_string_free(rval_evaluator_t * pevaluator)631 static void rval_evaluator_string_free(rval_evaluator_t* pevaluator) {
632 	rval_evaluator_string_state_t* pstate = pevaluator->pvstate;
633 	free(pstate->string);
634 	free(pstate);
635 	free(pevaluator);
636 }
637 
rval_evaluator_alloc_from_string(char * string)638 rval_evaluator_t* rval_evaluator_alloc_from_string(char* string) {
639 	rval_evaluator_string_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_string_state_t));
640 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
641 
642 	pstate->string            = mlr_strdup_or_die(string);
643 	pevaluator->pprocess_func = rval_evaluator_string_func;
644 	pevaluator->pfree_func    = rval_evaluator_string_free;
645 
646 	pevaluator->pvstate = pstate;
647 	return pevaluator;
648 }
649 
650 // ----------------------------------------------------------------
651 typedef struct _rval_evaluator_boolean_literal_state_t {
652 	mv_t literal;
653 } rval_evaluator_boolean_literal_state_t;
654 
rval_evaluator_boolean_literal_func(void * pvstate,variables_t * pvars)655 mv_t rval_evaluator_boolean_literal_func(void* pvstate, variables_t* pvars) {
656 	rval_evaluator_boolean_literal_state_t* pstate = pvstate;
657 	return pstate->literal;
658 }
659 
rval_evaluator_boolean_literal_free(rval_evaluator_t * pevaluator)660 static void rval_evaluator_boolean_literal_free(rval_evaluator_t* pevaluator) {
661 	rval_evaluator_boolean_literal_state_t* pstate = pevaluator->pvstate;
662 	mv_free(&pstate->literal);
663 	free(pstate);
664 	free(pevaluator);
665 }
666 
rval_evaluator_alloc_from_boolean_literal(char * string)667 rval_evaluator_t* rval_evaluator_alloc_from_boolean_literal(char* string) {
668 	rval_evaluator_boolean_literal_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_boolean_literal_state_t));
669 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
670 
671 	if (streq(string, "true")) {
672 		pstate->literal = mv_from_true();
673 	} else if (streq(string, "false")) {
674 		pstate->literal = mv_from_false();
675 	} else {
676 		MLR_INTERNAL_CODING_ERROR();
677 	}
678 	pevaluator->pprocess_func = rval_evaluator_boolean_literal_func;
679 	pevaluator->pfree_func = rval_evaluator_boolean_literal_free;
680 
681 	pevaluator->pvstate = pstate;
682 	return pevaluator;
683 }
684 
rval_evaluator_alloc_from_boolean(int boolval)685 rval_evaluator_t* rval_evaluator_alloc_from_boolean(int boolval) {
686 	rval_evaluator_boolean_literal_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_boolean_literal_state_t));
687 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
688 
689 	pstate->literal = mv_from_bool(boolval);
690 	pevaluator->pprocess_func = rval_evaluator_boolean_literal_func;
691 	pevaluator->pfree_func = rval_evaluator_boolean_literal_free;
692 
693 	pevaluator->pvstate = pstate;
694 	return pevaluator;
695 }
696 
697 // ================================================================
698 // Example:
699 // $ mlr put -v '$y=ENV["X"]' ...
700 // AST BEGIN STATEMENTS (0):
701 // AST MAIN STATEMENTS (1):
702 // = (srec_assignment):
703 //     y (field_name).
704 //     env (env):
705 //         ENV (env).
706 //         X (numeric_literal).
707 // AST END STATEMENTS (0):
708 
709 // ----------------------------------------------------------------
710 typedef struct _rval_evaluator_environment_state_t {
711 	rval_evaluator_t* pname_evaluator;
712 } rval_evaluator_environment_state_t;
713 
rval_evaluator_environment_func(void * pvstate,variables_t * pvars)714 mv_t rval_evaluator_environment_func(void* pvstate, variables_t* pvars) {
715 	rval_evaluator_environment_state_t* pstate = pvstate;
716 
717 	mv_t mvname = pstate->pname_evaluator->pprocess_func(pstate->pname_evaluator->pvstate, pvars);
718 	if (mv_is_null(&mvname)) {
719 		return mv_absent();
720 	}
721 	char free_flags;
722 	char* strname = mv_format_val(&mvname, &free_flags);
723 	char* strvalue = getenv(strname);
724 	if (strvalue == NULL) {
725 		mv_free(&mvname);
726 		if (free_flags & FREE_ENTRY_VALUE)
727 			free(strname);
728 		return mv_empty();
729 	}
730 	mv_t rv = mv_from_string(strvalue, NO_FREE);
731 	mv_free(&mvname);
732 	if (free_flags & FREE_ENTRY_VALUE)
733 		free(strname);
734 	return rv;
735 }
736 
rval_evaluator_environment_free(rval_evaluator_t * pevaluator)737 static void rval_evaluator_environment_free(rval_evaluator_t* pevaluator) {
738 	rval_evaluator_environment_state_t* pstate = pevaluator->pvstate;
739 	pstate->pname_evaluator->pfree_func(pstate->pname_evaluator);
740 	free(pstate);
741 	free(pevaluator);
742 }
743 
rval_evaluator_alloc_from_environment(mlr_dsl_ast_node_t * pnode,fmgr_t * pfmgr,int type_inferencing,int context_flags)744 rval_evaluator_t* rval_evaluator_alloc_from_environment(mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr,
745 	int type_inferencing, int context_flags)
746 {
747 	rval_evaluator_environment_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_environment_state_t));
748 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
749 
750 	mlr_dsl_ast_node_t* pnamenode = pnode->pchildren->phead->pnext->pvvalue;
751 
752 	pstate->pname_evaluator = rval_evaluator_alloc_from_ast(pnamenode, pfmgr, type_inferencing, context_flags);
753 	pevaluator->pprocess_func = rval_evaluator_environment_func;
754 	pevaluator->pfree_func = rval_evaluator_environment_free;
755 
756 	pevaluator->pvstate = pstate;
757 	return pevaluator;
758 }
759 
760 // ================================================================
rval_evaluator_NF_func(void * pvstate,variables_t * pvars)761 mv_t rval_evaluator_NF_func(void* pvstate, variables_t* pvars) {
762 	if (pvars->pinrec == NULL) {
763 		// E.g. in a 'begin {...}' or 'end {...}' block
764 		return mv_absent();
765 	} else{
766 		return mv_from_int(pvars->pinrec->field_count);
767 	}
768 }
rval_evaluator_NF_free(rval_evaluator_t * pevaluator)769 static void rval_evaluator_NF_free(rval_evaluator_t* pevaluator) {
770 	free(pevaluator);
771 }
rval_evaluator_alloc_from_NF()772 rval_evaluator_t* rval_evaluator_alloc_from_NF() {
773 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
774 	pevaluator->pvstate = NULL;
775 	pevaluator->pprocess_func = rval_evaluator_NF_func;
776 	pevaluator->pfree_func = rval_evaluator_NF_free;
777 	return pevaluator;
778 }
779 
780 // ----------------------------------------------------------------
rval_evaluator_NR_func(void * pvstate,variables_t * pvars)781 mv_t rval_evaluator_NR_func(void* pvstate, variables_t* pvars) {
782 	return mv_from_int(pvars->pctx->nr);
783 }
rval_evaluator_NR_free(rval_evaluator_t * pevaluator)784 static void rval_evaluator_NR_free(rval_evaluator_t* pevaluator) {
785 	free(pevaluator);
786 }
rval_evaluator_alloc_from_NR()787 rval_evaluator_t* rval_evaluator_alloc_from_NR() {
788 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
789 	pevaluator->pvstate = NULL;
790 	pevaluator->pprocess_func = rval_evaluator_NR_func;
791 	pevaluator->pfree_func = rval_evaluator_NR_free;
792 	return pevaluator;
793 }
794 
795 // ----------------------------------------------------------------
rval_evaluator_FNR_func(void * pvstate,variables_t * pvars)796 mv_t rval_evaluator_FNR_func(void* pvstate, variables_t* pvars) {
797 	return mv_from_int(pvars->pctx->fnr);
798 }
rval_evaluator_FNR_free(rval_evaluator_t * pevaluator)799 static void rval_evaluator_FNR_free(rval_evaluator_t* pevaluator) {
800 	free(pevaluator);
801 }
rval_evaluator_alloc_from_FNR()802 rval_evaluator_t* rval_evaluator_alloc_from_FNR() {
803 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
804 	pevaluator->pvstate = NULL;
805 	pevaluator->pprocess_func = rval_evaluator_FNR_func;
806 	pevaluator->pfree_func = rval_evaluator_FNR_free;
807 	return pevaluator;
808 }
809 
810 // ----------------------------------------------------------------
rval_evaluator_FILENAME_func(void * pvstate,variables_t * pvars)811 mv_t rval_evaluator_FILENAME_func(void* pvstate, variables_t* pvars) {
812 	return mv_from_string_no_free(pvars->pctx->filename);
813 }
rval_evaluator_FILENAME_free(rval_evaluator_t * pevaluator)814 static void rval_evaluator_FILENAME_free(rval_evaluator_t* pevaluator) {
815 	free(pevaluator);
816 }
817 
rval_evaluator_alloc_from_FILENAME()818 rval_evaluator_t* rval_evaluator_alloc_from_FILENAME() {
819 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
820 	pevaluator->pvstate = NULL;
821 	pevaluator->pprocess_func = rval_evaluator_FILENAME_func;
822 	pevaluator->pfree_func = rval_evaluator_FILENAME_free;
823 	return pevaluator;
824 }
825 
826 // ----------------------------------------------------------------
rval_evaluator_FILENUM_func(void * pvstate,variables_t * pvars)827 mv_t rval_evaluator_FILENUM_func(void* pvstate, variables_t* pvars) {
828 	return mv_from_int(pvars->pctx->filenum);
829 }
rval_evaluator_FILENUM_free(rval_evaluator_t * pevaluator)830 static void rval_evaluator_FILENUM_free(rval_evaluator_t* pevaluator) {
831 	free(pevaluator);
832 }
rval_evaluator_alloc_from_FILENUM()833 rval_evaluator_t* rval_evaluator_alloc_from_FILENUM() {
834 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
835 	pevaluator->pvstate = NULL;
836 	pevaluator->pprocess_func = rval_evaluator_FILENUM_func;
837 	pevaluator->pfree_func = rval_evaluator_FILENUM_free;
838 	return pevaluator;
839 }
840 
841 // ----------------------------------------------------------------
rval_evaluator_PI_func(void * pvstate,variables_t * pvars)842 mv_t rval_evaluator_PI_func(void* pvstate, variables_t* pvars) {
843 	return mv_from_float(M_PI);
844 }
rval_evaluator_PI_free(rval_evaluator_t * pevaluator)845 static void rval_evaluator_PI_free(rval_evaluator_t* pevaluator) {
846 	free(pevaluator);
847 }
rval_evaluator_alloc_from_M_PI()848 rval_evaluator_t* rval_evaluator_alloc_from_M_PI() {
849 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
850 	pevaluator->pvstate = NULL;
851 	pevaluator->pprocess_func = rval_evaluator_PI_func;
852 	pevaluator->pfree_func = rval_evaluator_PI_free;
853 	return pevaluator;
854 }
855 
856 // ----------------------------------------------------------------
rval_evaluator_E_func(void * pvstate,variables_t * pvars)857 mv_t rval_evaluator_E_func(void* pvstate, variables_t* pvars) {
858 	return mv_from_float(M_E);
859 }
rval_evaluator_E_free(rval_evaluator_t * pevaluator)860 static void rval_evaluator_E_free(rval_evaluator_t* pevaluator) {
861 	free(pevaluator);
862 }
rval_evaluator_alloc_from_M_E()863 rval_evaluator_t* rval_evaluator_alloc_from_M_E() {
864 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
865 	pevaluator->pvstate = NULL;
866 	pevaluator->pprocess_func = rval_evaluator_E_func;
867 	pevaluator->pfree_func = rval_evaluator_E_free;
868 	return pevaluator;
869 }
870 
871 // ----------------------------------------------------------------
rval_evaluator_IPS_func(void * pvstate,variables_t * pvars)872 mv_t rval_evaluator_IPS_func(void* pvstate, variables_t* pvars) {
873 	return mv_from_string_no_free(pvars->pctx->ips);
874 }
rval_evaluator_IPS_free(rval_evaluator_t * pevaluator)875 static void rval_evaluator_IPS_free(rval_evaluator_t* pevaluator) {
876 	free(pevaluator);
877 }
rval_evaluator_alloc_from_IPS()878 rval_evaluator_t* rval_evaluator_alloc_from_IPS() {
879 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
880 	pevaluator->pvstate = NULL;
881 	pevaluator->pprocess_func = rval_evaluator_IPS_func;
882 	pevaluator->pfree_func = rval_evaluator_IPS_free;
883 	return pevaluator;
884 }
885 
886 // ----------------------------------------------------------------
rval_evaluator_IFS_func(void * pvstate,variables_t * pvars)887 mv_t rval_evaluator_IFS_func(void* pvstate, variables_t* pvars) {
888 	return mv_from_string_no_free(pvars->pctx->ifs);
889 }
rval_evaluator_IFS_free(rval_evaluator_t * pevaluator)890 static void rval_evaluator_IFS_free(rval_evaluator_t* pevaluator) {
891 	free(pevaluator);
892 }
rval_evaluator_alloc_from_IFS()893 rval_evaluator_t* rval_evaluator_alloc_from_IFS() {
894 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
895 	pevaluator->pvstate = NULL;
896 	pevaluator->pprocess_func = rval_evaluator_IFS_func;
897 	pevaluator->pfree_func = rval_evaluator_IFS_free;
898 	return pevaluator;
899 }
900 
901 // ----------------------------------------------------------------
rval_evaluator_IRS_func(void * pvstate,variables_t * pvars)902 mv_t rval_evaluator_IRS_func(void* pvstate, variables_t* pvars) {
903 	context_t* pctx = pvars->pctx;
904 	return mv_from_string_no_free(
905 		pctx->auto_line_term_detected
906 			? pctx->auto_line_term
907 			: pctx->irs
908 	);
909 }
rval_evaluator_IRS_free(rval_evaluator_t * pevaluator)910 static void rval_evaluator_IRS_free(rval_evaluator_t* pevaluator) {
911 	free(pevaluator);
912 }
rval_evaluator_alloc_from_IRS()913 rval_evaluator_t* rval_evaluator_alloc_from_IRS() {
914 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
915 	pevaluator->pvstate = NULL;
916 	pevaluator->pprocess_func = rval_evaluator_IRS_func;
917 	pevaluator->pfree_func = rval_evaluator_IRS_free;
918 	return pevaluator;
919 }
920 
921 // ----------------------------------------------------------------
rval_evaluator_OPS_func(void * pvstate,variables_t * pvars)922 mv_t rval_evaluator_OPS_func(void* pvstate, variables_t* pvars) {
923 	return mv_from_string_no_free(pvars->pctx->ops);
924 }
rval_evaluator_OPS_free(rval_evaluator_t * pevaluator)925 static void rval_evaluator_OPS_free(rval_evaluator_t* pevaluator) {
926 	free(pevaluator);
927 }
rval_evaluator_alloc_from_OPS()928 rval_evaluator_t* rval_evaluator_alloc_from_OPS() {
929 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
930 	pevaluator->pvstate = NULL;
931 	pevaluator->pprocess_func = rval_evaluator_OPS_func;
932 	pevaluator->pfree_func = rval_evaluator_OPS_free;
933 	return pevaluator;
934 }
935 
936 // ----------------------------------------------------------------
rval_evaluator_OFS_func(void * pvstate,variables_t * pvars)937 mv_t rval_evaluator_OFS_func(void* pvstate, variables_t* pvars) {
938 	return mv_from_string_no_free(pvars->pctx->ofs);
939 }
rval_evaluator_OFS_free(rval_evaluator_t * pevaluator)940 static void rval_evaluator_OFS_free(rval_evaluator_t* pevaluator) {
941 	free(pevaluator);
942 }
rval_evaluator_alloc_from_OFS()943 rval_evaluator_t* rval_evaluator_alloc_from_OFS() {
944 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
945 	pevaluator->pvstate = NULL;
946 	pevaluator->pprocess_func = rval_evaluator_OFS_func;
947 	pevaluator->pfree_func = rval_evaluator_OFS_free;
948 	return pevaluator;
949 }
950 
951 // ----------------------------------------------------------------
rval_evaluator_ORS_func(void * pvstate,variables_t * pvars)952 mv_t rval_evaluator_ORS_func(void* pvstate, variables_t* pvars) {
953 	context_t* pctx = pvars->pctx;
954 	return mv_from_string_no_free(
955 		pctx->auto_line_term_detected
956 			? pctx->auto_line_term
957 			: pctx->ors
958 	);
959 }
rval_evaluator_ORS_free(rval_evaluator_t * pevaluator)960 static void rval_evaluator_ORS_free(rval_evaluator_t* pevaluator) {
961 	free(pevaluator);
962 }
rval_evaluator_alloc_from_ORS()963 rval_evaluator_t* rval_evaluator_alloc_from_ORS() {
964 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
965 	pevaluator->pvstate = NULL;
966 	pevaluator->pprocess_func = rval_evaluator_ORS_func;
967 	pevaluator->pfree_func = rval_evaluator_ORS_free;
968 	return pevaluator;
969 }
970 
971 // ================================================================
rval_evaluator_alloc_from_context_variable(char * variable_name)972 rval_evaluator_t* rval_evaluator_alloc_from_context_variable(char* variable_name) {
973 	if        (streq(variable_name, "NF"))       { return rval_evaluator_alloc_from_NF();
974 	} else if (streq(variable_name, "NR"))       { return rval_evaluator_alloc_from_NR();
975 	} else if (streq(variable_name, "FNR"))      { return rval_evaluator_alloc_from_FNR();
976 	} else if (streq(variable_name, "FILENAME")) { return rval_evaluator_alloc_from_FILENAME();
977 	} else if (streq(variable_name, "FILENUM"))  { return rval_evaluator_alloc_from_FILENUM();
978 	} else if (streq(variable_name, "M_PI"))     { return rval_evaluator_alloc_from_M_PI();
979 	} else if (streq(variable_name, "M_E"))      { return rval_evaluator_alloc_from_M_E();
980 	} else if (streq(variable_name, "IPS"))      { return rval_evaluator_alloc_from_IPS();
981 	} else if (streq(variable_name, "IFS"))      { return rval_evaluator_alloc_from_IFS();
982 	} else if (streq(variable_name, "IRS"))      { return rval_evaluator_alloc_from_IRS();
983 	} else if (streq(variable_name, "OPS"))      { return rval_evaluator_alloc_from_OPS();
984 	} else if (streq(variable_name, "OFS"))      { return rval_evaluator_alloc_from_OFS();
985 	} else if (streq(variable_name, "ORS"))      { return rval_evaluator_alloc_from_ORS();
986 	} else  { return NULL;
987 	}
988 }
989 
990 // ================================================================
991 typedef struct _rval_evaluator_from_local_variable_state_t {
992 	int vardef_frame_relative_index;
993 } rval_evaluator_from_local_variable_state_t;
994 
rval_evaluator_from_local_variable_func(void * pvstate,variables_t * pvars)995 mv_t rval_evaluator_from_local_variable_func(void* pvstate, variables_t* pvars) {
996 	rval_evaluator_from_local_variable_state_t* pstate = pvstate;
997 	local_stack_frame_t* pframe = local_stack_get_top_frame(pvars->plocal_stack);
998 	mv_t val = local_stack_frame_get_terminal_from_nonindexed(pframe, pstate->vardef_frame_relative_index);
999 	return mv_copy(&val);
1000 }
1001 
rval_evaluator_from_local_variable_free(rval_evaluator_t * pevaluator)1002 static void rval_evaluator_from_local_variable_free(rval_evaluator_t* pevaluator) {
1003 	rval_evaluator_from_local_variable_state_t* pstate = pevaluator->pvstate;
1004 	free(pstate);
1005 	free(pevaluator);
1006 }
1007 
rval_evaluator_alloc_from_local_variable(int vardef_frame_relative_index)1008 rval_evaluator_t* rval_evaluator_alloc_from_local_variable(int vardef_frame_relative_index) {
1009 	rval_evaluator_from_local_variable_state_t* pstate = mlr_malloc_or_die(
1010 		sizeof(rval_evaluator_from_local_variable_state_t));
1011 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
1012 
1013 	MLR_INTERNAL_CODING_ERROR_IF(vardef_frame_relative_index == MD_UNUSED_INDEX);
1014 	pstate->vardef_frame_relative_index = vardef_frame_relative_index;
1015 	pevaluator->pprocess_func    = rval_evaluator_from_local_variable_func;
1016 	pevaluator->pfree_func       = rval_evaluator_from_local_variable_free;
1017 
1018 	pevaluator->pvstate = pstate;
1019 	return pevaluator;
1020 }
1021 
1022 // ----------------------------------------------------------------
1023 typedef struct _rval_evaluator_mv_state_t {
1024 	mv_t literal;
1025 } rval_evaluator_mv_state_t;
1026 
rval_evaluator_mv_process(void * pvstate,variables_t * pvars)1027 mv_t rval_evaluator_mv_process(void* pvstate, variables_t* pvars) {
1028 	rval_evaluator_mv_state_t* pstate = pvstate;
1029 	return mv_copy(&pstate->literal);
1030 
1031 }
rval_evaluator_mv_free(rval_evaluator_t * pevaluator)1032 static void rval_evaluator_mv_free(rval_evaluator_t* pevaluator) {
1033 	rval_evaluator_mv_state_t* pstate = pevaluator->pvstate;
1034 	mv_free(&pstate->literal);
1035 	free(pstate);
1036 	free(pevaluator);
1037 }
1038 
rval_evaluator_alloc_from_mlrval(mv_t * pval)1039 rval_evaluator_t* rval_evaluator_alloc_from_mlrval(mv_t* pval) {
1040 	rval_evaluator_mv_state_t* pstate = mlr_malloc_or_die(sizeof(rval_evaluator_mv_state_t));
1041 	rval_evaluator_t* pevaluator = mlr_malloc_or_die(sizeof(rval_evaluator_t));
1042 
1043 	pstate->literal = mv_copy(pval);
1044 	pevaluator->pprocess_func = rval_evaluator_mv_process;
1045 	pevaluator->pfree_func = rval_evaluator_mv_free;
1046 
1047 	pevaluator->pvstate = pstate;
1048 	return pevaluator;
1049 }
1050 
1051 // ================================================================
1052 // Type-inferenced srec-field getters
1053 
1054 // ----------------------------------------------------------------
get_srec_value_string_only(char * field_name,lrec_t * pinrec,lhmsmv_t * ptyped_overlay)1055 mv_t get_srec_value_string_only(char* field_name, lrec_t* pinrec, lhmsmv_t* ptyped_overlay) {
1056 	// See comments in rval_evaluator.h and mapper_put.c regarding the typed-overlay map.
1057 	mv_t* poverlay = lhmsmv_get(ptyped_overlay, field_name);
1058 	mv_t rv;
1059 	if (poverlay != NULL) {
1060 		// The lrec-evaluator logic will free its inputs and allocate new outputs, so we must copy
1061 		// a value here to feed into that. Otherwise the typed-overlay map would have its contents
1062 		// freed out from underneath it by the evaluator functions.
1063 		rv = mv_copy(poverlay);
1064 	} else {
1065 		rv = mv_ref_type_infer_string(lrec_get(pinrec, field_name));
1066 		rv = mv_copy(&rv);
1067 	}
1068 	return rv;
1069 }
1070 
1071 // ----------------------------------------------------------------
get_srec_value_string_float(char * field_name,lrec_t * pinrec,lhmsmv_t * ptyped_overlay)1072 mv_t get_srec_value_string_float(char* field_name, lrec_t* pinrec, lhmsmv_t* ptyped_overlay) {
1073 	// See comments in rval_evaluator.h and mapper_put.c regarding the typed-overlay map.
1074 	mv_t* poverlay = lhmsmv_get(ptyped_overlay, field_name);
1075 	mv_t rv;
1076 	if (poverlay != NULL) {
1077 		// The lrec-evaluator logic will free its inputs and allocate new outputs, so we must copy
1078 		// a value here to feed into that. Otherwise the typed-overlay map would have its contents
1079 		// freed out from underneath it by the evaluator functions.
1080 		rv = mv_copy(poverlay);
1081 	} else {
1082 		rv = mv_ref_type_infer_string_or_float(lrec_get(pinrec, field_name));
1083 		rv = mv_copy(&rv);
1084 	}
1085 	return rv;
1086 }
1087 
1088 // ----------------------------------------------------------------
get_srec_value_string_float_int(char * field_name,lrec_t * pinrec,lhmsmv_t * ptyped_overlay)1089 mv_t get_srec_value_string_float_int(char* field_name, lrec_t* pinrec, lhmsmv_t* ptyped_overlay) {
1090 	// See comments in rval_evaluator.h and mapper_put.c regarding the typed-overlay map.
1091 	mv_t* poverlay = lhmsmv_get(ptyped_overlay, field_name);
1092 	mv_t rv;
1093 	if (poverlay != NULL) {
1094 		// The lrec-evaluator logic will free its inputs and allocate new outputs, so we must copy
1095 		// a value here to feed into that. Otherwise the typed-overlay map would have its contents
1096 		// freed out from underneath it by the evaluator functions.
1097 		rv = mv_copy(poverlay);
1098 	} else {
1099 		rv = mv_ref_type_infer_string_or_float_or_int(lrec_get(pinrec, field_name));
1100 		rv = mv_copy(&rv);
1101 	}
1102 	return rv;
1103 }
1104 
1105 // ----------------------------------------------------------------
get_copy_srec_value_string_only_aux(lrece_t * pentry,lhmsmv_t * ptyped_overlay)1106 mv_t get_copy_srec_value_string_only_aux(lrece_t* pentry, lhmsmv_t* ptyped_overlay) {
1107 	// See comments in rval_evaluator.h and mapper_put.c regarding the typed-overlay map.
1108 	mv_t* poverlay = lhmsmv_get(ptyped_overlay, pentry->key);
1109 	mv_t rv;
1110 	if (poverlay != NULL) {
1111 		// The lrec-evaluator logic will free its inputs and allocate new outputs, so we must copy
1112 		// a value here to feed into that. Otherwise the typed-overlay map would have its contents
1113 		// freed out from underneath it by the evaluator functions.
1114 		rv = mv_copy(poverlay);
1115 	} else {
1116 		if (pentry->value == NULL) {
1117 			rv = mv_absent();
1118 		} else if (*pentry->value == 0) {
1119 			rv = mv_empty();
1120 		} else {
1121 			rv = mv_from_string_with_free(mlr_strdup_or_die(pentry->value));
1122 		}
1123 	}
1124 	return rv;
1125 }
1126 
1127 // ----------------------------------------------------------------
get_copy_srec_value_string_float_aux(lrece_t * pentry,lhmsmv_t * ptyped_overlay)1128 mv_t get_copy_srec_value_string_float_aux(lrece_t* pentry, lhmsmv_t* ptyped_overlay) {
1129 	// See comments in rval_evaluator.h and mapper_put.c regarding the typed-overlay map.
1130 	mv_t* poverlay = lhmsmv_get(ptyped_overlay, pentry->key);
1131 	mv_t rv;
1132 	if (poverlay != NULL) {
1133 		// The lrec-evaluator logic will free its inputs and allocate new outputs, so we must copy
1134 		// a value here to feed into that. Otherwise the typed-overlay map would have its contents
1135 		// freed out from underneath it by the evaluator functions.
1136 		rv = mv_copy(poverlay);
1137 	} else {
1138 		if (pentry->value == NULL) {
1139 			rv = mv_absent();
1140 		} else if (*pentry->value == 0) {
1141 			rv = mv_empty();
1142 		} else {
1143 			double fltv;
1144 			if (mlr_try_float_from_string(pentry->value, &fltv)) {
1145 				rv = mv_from_float(fltv);
1146 			} else {
1147 				rv = mv_from_string_with_free(mlr_strdup_or_die(pentry->value));
1148 			}
1149 		}
1150 	}
1151 	return rv;
1152 }
1153 
1154 // ----------------------------------------------------------------
get_copy_srec_value_string_float_int_aux(lrece_t * pentry,lhmsmv_t * ptyped_overlay)1155 mv_t get_copy_srec_value_string_float_int_aux(lrece_t* pentry, lhmsmv_t* ptyped_overlay) {
1156 	// See comments in rval_evaluator.h and mapper_put.c regarding the typed-overlay map.
1157 	mv_t* poverlay = lhmsmv_get(ptyped_overlay, pentry->key);
1158 	mv_t rv;
1159 	if (poverlay != NULL) {
1160 		// The lrec-evaluator logic will free its inputs and allocate new outputs, so we must copy
1161 		// a value here to feed into that. Otherwise the typed-overlay map would have its contents
1162 		// freed out from underneath it by the evaluator functions.
1163 		rv = mv_copy(poverlay);
1164 	} else {
1165 		if (pentry->value == NULL) {
1166 			rv = mv_absent();
1167 		} else if (*pentry->value == 0) {
1168 			rv = mv_empty();
1169 		} else {
1170 			long long intv;
1171 			double fltv;
1172 			if (mlr_try_int_from_string(pentry->value, &intv)) {
1173 				rv = mv_from_int(intv);
1174 			} else if (mlr_try_float_from_string(pentry->value, &fltv)) {
1175 				rv = mv_from_float(fltv);
1176 			} else {
1177 				rv = mv_from_string_with_free(mlr_strdup_or_die(pentry->value));
1178 			}
1179 		}
1180 	}
1181 	return rv;
1182 }
1183