void mlr_dsl_cst_free(mlr_dsl_cst_t* pcst) { if (pcst == NULL) return; for (sllve_t* pe = pcst->pbegin_statements->phead; pe != NULL; pe = pe->pnext) cst_statement_free(pe->pvvalue); for (sllve_t* pe = pcst->pmain_statements->phead; pe != NULL; pe = pe->pnext) cst_statement_free(pe->pvvalue); for (sllve_t* pe = pcst->pend_statements->phead; pe != NULL; pe = pe->pnext) cst_statement_free(pe->pvvalue); sllv_free(pcst->pbegin_statements); sllv_free(pcst->pmain_statements); sllv_free(pcst->pend_statements); free(pcst); }
static void lrec_reader_stdio_json_free(lrec_reader_t* preader) { lrec_reader_stdio_json_state_t* pstate = preader->pvstate; for (sllve_t* pe = pstate->ptop_level_json_objects->phead; pe != NULL; pe = pe->pnext) { json_value_t* top_level_json_object = pe->pvvalue; json_free_value(top_level_json_object); } sllv_free(pstate->ptop_level_json_objects); for (sllve_t* pf = pstate->precords->phead; pf != NULL; pf = pf->pnext) { lrec_t* prec = pf->pvvalue; lrec_free(prec); } sllv_free(pstate->precords); pstate->precords = NULL; free(pstate); free(preader); }
// ---------------------------------------------------------------- static void free_unset(mlr_dsl_cst_statement_t* pstatement, context_t* _) { unset_state_t* pstate = pstatement->pvstate; for (sllve_t* pe = pstate->punset_items->phead; pe != NULL; pe = pe->pnext) { free_unset_item(pe->pvvalue); } sllv_free(pstate->punset_items); free(pstate); }
// ---------------------------------------------------------------- static void free_if_head(mlr_dsl_cst_statement_t* pstatement, context_t* pctx) { if_head_state_t* pstate = pstatement->pvstate; if (pstate->pif_chain_statements != NULL) { for (sllve_t* pe = pstate->pif_chain_statements->phead; pe != NULL; pe = pe->pnext) mlr_dsl_cst_statement_free(pe->pvvalue, pctx); sllv_free(pstate->pif_chain_statements); } free(pstate); }
// ---------------------------------------------------------------- void mlr_dsl_ast_node_free(mlr_dsl_ast_node_t* pnode) { if (pnode->pchildren) { for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) { mlr_dsl_ast_node_t* pchild = pe->pvvalue; mlr_dsl_ast_node_free(pchild); } sllv_free(pnode->pchildren); } free(pnode->text); free(pnode); }
// ---------------------------------------------------------------- static void free_indexed_local_variable_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) { indexed_local_variable_assignment_state_t* pstate = pstatement->pvstate; for (sllve_t* pe = pstate->plhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) { rval_evaluator_t* pev = pe->pvvalue; pev->pfree_func(pev); } sllv_free(pstate->plhs_keylist_evaluators); pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator); free(pstate); }
static void free_unset_item(unset_item_t* punset_item) { if (punset_item->pkeylist_evaluators != NULL) { for (sllve_t* pe = punset_item->pkeylist_evaluators->phead; pe != NULL; pe = pe->pnext) { rval_evaluator_t* phandler = pe->pvvalue; phandler->pfree_func(phandler); } sllv_free(punset_item->pkeylist_evaluators); } if (punset_item->psrec_field_name_evaluator != NULL) { punset_item->psrec_field_name_evaluator->pfree_func(punset_item->psrec_field_name_evaluator); } free(punset_item); }
static void lrec_writer_pprint_free(lrec_writer_t* pwriter) { lrec_writer_pprint_state_t* pstate = pwriter->pvstate; if (pstate->precords != NULL) { sllv_free(pstate->precords); pstate->precords = NULL; } if (pstate->pprev_keys != NULL) { slls_free(pstate->pprev_keys); pstate->pprev_keys = NULL; } free(pstate); free(pwriter); }
// ---------------------------------------------------------------- void cli_opts_free(cli_opts_t* popts) { if (popts->plrec_reader->pfree_func != NULL) popts->plrec_reader->pfree_func(popts->plrec_reader->pvstate); for (sllve_t* pe = popts->pmapper_list->phead; pe != NULL; pe = pe->pnext) { mapper_t* pmapper = pe->pvdata; pmapper->pfree_func(pmapper->pvstate); } sllv_free(popts->pmapper_list); popts->plrec_writer->pfree_func(popts->plrec_writer->pvstate); free(popts); }
// ---------------------------------------------------------------- static void drive_lrec(lrec_t* pinrec, context_t* pctx, sllve_t* pmapper_list_head, lrec_writer_t* plrec_writer, FILE* output_stream) { sllv_t* outrecs = chain_map(pinrec, pctx, pmapper_list_head); if (outrecs != NULL) { for (sllve_t* pe = outrecs->phead; pe != NULL; pe = pe->pnext) { lrec_t* poutrec = pe->pvdata; if (poutrec != NULL) // writer frees records (sllv void-star payload) plrec_writer->pprocess_func(output_stream, poutrec, plrec_writer->pvstate); } sllv_free(outrecs); // we free the list } }
// ---------------------------------------------------------------- static void free_oosvar_assignment(mlr_dsl_cst_statement_t* pstatement, context_t* _) { oosvar_assignment_state_t* pstate = pstatement->pvstate; for (sllve_t* pe = pstate->plhs_keylist_evaluators->phead; pe != NULL; pe = pe->pnext) { rval_evaluator_t* pev = pe->pvvalue; pev->pfree_func(pev); } sllv_free(pstate->plhs_keylist_evaluators); if (pstate->prhs_xevaluator != NULL) { pstate->prhs_xevaluator->pfree_func(pstate->prhs_xevaluator); } free(pstate); }
void ap_free(ap_state_t* pstate) { if (pstate == NULL) return; for (sllve_t* pe = pstate->pflag_defs->phead; pe != NULL; pe = pe->pnext) { ap_flag_def_t* pdef = pe->pvdata; if (pdef->type == AP_STRING_LIST_FLAG && pdef->pval != NULL) { slls_t** pplist = pdef->pval; if (*pplist != NULL) slls_free(*pplist); } free(pdef); } sllv_free(pstate->pflag_defs); free(pstate); }
// ---------------------------------------------------------------- void cli_opts_free(cli_opts_t* popts) { if (popts == NULL) return; popts->plrec_reader->pfree_func(popts->plrec_reader); for (sllve_t* pe = popts->pmapper_list->phead; pe != NULL; pe = pe->pnext) { mapper_t* pmapper = pe->pvvalue; pmapper->pfree_func(pmapper); } sllv_free(popts->pmapper_list); popts->plrec_writer->pfree_func(popts->plrec_writer); free(popts); free_opt_singletons(); }
static sllv_t* chain_map(lrec_t* pinrec, context_t* pctx, sllve_t* pmapper_list_head) { mapper_t* pmapper = pmapper_list_head->pvdata; sllv_t* outrecs = pmapper->pprocess_func(pinrec, pctx, pmapper->pvstate); if (pmapper_list_head->pnext == NULL) { return outrecs; } else if (outrecs == NULL) { // xxx cmt return NULL; } else { sllv_t* nextrecs = sllv_alloc(); for (sllve_t* pe = outrecs->phead; pe != NULL; pe = pe->pnext) { lrec_t* poutrec = pe->pvdata; sllv_t* nextrecsi = chain_map(poutrec, pctx, pmapper_list_head->pnext); nextrecs = sllv_append(nextrecs, nextrecsi); } sllv_free(outrecs); return nextrecs; } }
static void cst_statement_free(mlr_dsl_cst_statement_t* pstatement) { for (sllve_t* pe = pstatement->pitems->phead; pe != NULL; pe = pe->pnext) cst_statement_item_free(pe->pvvalue); sllv_free(pstatement->pitems); free(pstatement); }
// ---------------------------------------------------------------- static void mlr_dsl_ast_free_statement_list(sllv_t* plist) { for (sllve_t* pe = plist->phead; pe != NULL; pe = pe->pnext) mlr_dsl_ast_node_free(pe->pvvalue); sllv_free(plist); }
// The stdio-JSON lrec-reader is non-streaming: we ingest all records here in the start-of-file hook. // Then in the process method we pop one lrec off the list at a time, until they are all exhausted. // This is in contrast to other Miller lrec-readers. // // It would be possible to extend the streaming framework to also have an end-of-file hook // which we could use here to free parsed-JSON data. However, we simply leverage the start-of-file // hook for the *next* file (if any) or the free method (if not): these free parsed-JSON structures // from the previous file (if any). static void lrec_reader_stdio_json_sof(void* pvstate, void* pvhandle) { lrec_reader_stdio_json_state_t* pstate = pvstate; file_ingestor_stdio_state_t* phandle = pvhandle; json_char* json_input = (json_char*)phandle->sof; json_value_t* parsed_top_level_json; json_char error_buf[JSON_ERROR_MAX]; if (pstate->ptop_level_json_objects != NULL) { for (sllve_t* pe = pstate->ptop_level_json_objects->phead; pe != NULL; pe = pe->pnext) { json_value_t* top_level_json_object = pe->pvvalue; json_value_free(top_level_json_object); } sllv_free(pstate->ptop_level_json_objects); } if (pstate->precords != NULL) { for (sllve_t* pf = pstate->precords->phead; pf != NULL; pf = pf->pnext) { lrec_t* prec = pf->pvvalue; lrec_free(prec); } sllv_free(pstate->precords); } pstate->ptop_level_json_objects = sllv_alloc(); pstate->precords = sllv_alloc(); // This enables us to handle input of the form // // { "a" : 1 } // { "b" : 2 } // { "c" : 3 } // // in addition to // // [ // { "a" : 1 } // { "b" : 2 } // { "c" : 3 } // ] // // This is in line with what jq can handle. In this case, json_parse will return // once for each top-level item and will give us back a pointer to the start of // the rest of the input stream, so we can call json_parse on the rest until it is // all exhausted. json_char* item_start = json_input; int length = phandle->eof - phandle->sof; while (TRUE) { parsed_top_level_json = json_parse(item_start, length, error_buf, &item_start); if (parsed_top_level_json == NULL) { fprintf(stderr, "Unable to parse JSON data: %s\n", error_buf); exit(1); } // The lrecs have their string pointers pointing into the parsed-JSON objects (for // efficiency) so it's important we not free the latter until our free method. reference_json_objects_as_lrecs(pstate->precords, parsed_top_level_json, pstate->json_flatten_separator); if (item_start == NULL) break; if (*item_start == 0) break; length -= (item_start - json_input); json_input = item_start; } }
// ---------------------------------------------------------------- static void print_and_free_record_list(sllv_t* precords, FILE* output_stream, char* ors, char ofs, int left_align) { if (precords->length == 0) { sllv_free(precords); return; } lrec_t* prec1 = precords->phead->pvvalue; int* max_widths = mlr_malloc_or_die(sizeof(int) * prec1->field_count); int j = 0; for (lrece_t* pe = prec1->phead; pe != NULL; pe = pe->pnext, j++) { max_widths[j] = strlen_for_utf8_display(pe->key); } for (sllve_t* pnode = precords->phead; pnode != NULL; pnode = pnode->pnext) { lrec_t* prec = pnode->pvvalue; j = 0; for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext, j++) { int width = strlen_for_utf8_display(pe->value); if (width > max_widths[j]) max_widths[j] = width; } } int onr = 0; for (sllve_t* pnode = precords->phead; pnode != NULL; pnode = pnode->pnext, onr++) { lrec_t* prec = pnode->pvvalue; if (onr == 0) { j = 0; for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext, j++) { if (j > 0) { fputc(ofs, output_stream); } if (left_align) { if (pe->pnext == NULL) { fprintf(output_stream, "%s", pe->key); } else { // "%-*s" fprintf format isn't correct for non-ASCII UTF-8 fprintf(output_stream, "%s", pe->key); int d = max_widths[j] - strlen_for_utf8_display(pe->key); for (int i = 0; i < d; i++) fputc(ofs, output_stream); } } else { int d = max_widths[j] - strlen_for_utf8_display(pe->key); for (int i = 0; i < d; i++) fputc(ofs, output_stream); fprintf(output_stream, "%s", pe->key); } } fputs(ors, output_stream); } j = 0; for (lrece_t* pe = prec->phead; pe != NULL; pe = pe->pnext, j++) { if (j > 0) { fputc(ofs, output_stream); } char* value = pe->value; if (*value == 0) // empty string value = "-"; if (left_align) { if (pe->pnext == NULL) { fprintf(output_stream, "%s", value); } else { fprintf(output_stream, "%s", value); int d = max_widths[j] - strlen_for_utf8_display(value); for (int i = 0; i < d; i++) fputc(ofs, output_stream); } } else { int d = max_widths[j] - strlen_for_utf8_display(value); for (int i = 0; i < d; i++) fputc(ofs, output_stream); fprintf(output_stream, "%s", value); } } fputs(ors, output_stream); lrec_free(prec); // end of baton-pass } free(max_widths); sllv_free(precords); }