// ---------------------------------------------------------------- ex_ast_node_t* ex_ast_node_alloc_binary(char* text, ex_ast_node_type_t type, ex_ast_node_t* pa, ex_ast_node_t* pb) { ex_ast_node_t* pnode = ex_ast_node_alloc(text, type); pnode->pchildren = sllv_alloc(); sllv_append(pnode->pchildren, pa); sllv_append(pnode->pchildren, pb); return pnode; }
// ---------------------------------------------------------------- mlr_dsl_ast_node_t* mlr_dsl_ast_node_alloc_binary(char* text, int type, mlr_dsl_ast_node_t* pa, mlr_dsl_ast_node_t* pb) { mlr_dsl_ast_node_t* pnode = mlr_dsl_ast_node_alloc(text, type); pnode->pchildren = sllv_alloc(); sllv_append(pnode->pchildren, pa); sllv_append(pnode->pchildren, pb); return pnode; }
// ---------------------------------------------------------------- static void lrec_writer_pprint_process(FILE* output_stream, lrec_t* prec, void* pvstate) { lrec_writer_pprint_state_t* pstate = pvstate; int drain = FALSE; if (prec == NULL) { drain = TRUE; } else { if (pstate->pprev_keys != NULL && !lrec_keys_equal_list(prec, pstate->pprev_keys)) { drain = TRUE; } } if (drain) { if (pstate->num_blocks_written > 0LL) // separate blocks with empty line fputs(pstate->ors, output_stream); print_and_free_record_list(pstate->precords, output_stream, pstate->ors, pstate->ofs, pstate->left_align); if (pstate->pprev_keys != NULL) { slls_free(pstate->pprev_keys); pstate->pprev_keys = NULL; } pstate->precords = sllv_alloc(); pstate->num_blocks_written++; } if (prec != NULL) { sllv_append(pstate->precords, prec); if (pstate->pprev_keys == NULL) pstate->pprev_keys = mlr_copy_keys_from_record(prec); } }
static mlr_dsl_cst_statement_t* alloc_if_item(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pitemnode, mlr_dsl_ast_node_t* pexprnode, mlr_dsl_ast_node_t* plistnode, int type_inferencing, int context_flags) { if_item_state_t* pstate = mlr_malloc_or_die(sizeof(if_item_state_t)); MLR_INTERNAL_CODING_ERROR_IF(plistnode->subframe_var_count == MD_UNUSED_INDEX); cst_statement_block_t* pblock = cst_statement_block_alloc(plistnode->subframe_var_count); for (sllve_t* pe = plistnode->pchildren->phead; pe != NULL; pe = pe->pnext) { mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue; mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node, type_inferencing, context_flags); sllv_append(pblock->pstatements, pchild_statement); } pstate->pexpression_evaluator = pexprnode != NULL ? rval_evaluator_alloc_from_ast(pexprnode, pcst->pfmgr, type_inferencing, context_flags) // if-statement or elif-statement : rval_evaluator_alloc_from_boolean(TRUE); // else-statement return mlr_dsl_cst_statement_valloc_with_block( pitemnode, NULL, // handled by the containing if-head evaluator pblock, NULL, // handled by the containing if-head evaluator free_if_item, pstate); }
// ---------------------------------------------------------------- mlr_dsl_cst_statement_t* alloc_do_while(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode, int type_inferencing, int context_flags) { do_while_state_t* pstate = mlr_malloc_or_die(sizeof(do_while_state_t)); pstate->pexpression_evaluator = NULL; // Left child node is the list of statements in the body. // Right child node is the AST for the boolean expression. mlr_dsl_ast_node_t* pleft = pnode->pchildren->phead->pvvalue; mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue; MLR_INTERNAL_CODING_ERROR_IF(pleft->subframe_var_count == MD_UNUSED_INDEX); cst_statement_block_t* pblock = cst_statement_block_alloc(pright->subframe_var_count); for (sllve_t* pe = pleft->pchildren->phead; pe != NULL; pe = pe->pnext) { mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue; mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node, type_inferencing, context_flags); sllv_append(pblock->pstatements, pchild_statement); } pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast( pright, pcst->pfmgr, type_inferencing, context_flags); return mlr_dsl_cst_statement_valloc_with_block( pnode, handle_do_while, pblock, mlr_dsl_cst_handle_statement_block_with_break_continue, free_do_while, pstate); }
// ---------------------------------------------------------------- mlr_dsl_ast_node_t* mlr_dsl_ast_node_append_arg( mlr_dsl_ast_node_t* pa, mlr_dsl_ast_node_t* pb) { if (pa->pchildren == NULL) pa->pchildren = sllv_alloc(); sllv_append(pa->pchildren, pb); return pa; }
ex_ast_node_t* ex_ast_node_append_arg( ex_ast_node_t* pa, ex_ast_node_t* pb) { if (pa->pchildren == NULL) pa->pchildren = sllv_alloc(); sllv_append(pa->pchildren, pb); return pa; }
// ---------------------------------------------------------------- static sllv_t* make_records_het() { sllv_t* precords = sllv_alloc(); sllv_append(precords, lrec_literal_2("x","100", "b","10")); sllv_append(precords, lrec_literal_2("l","1", "b","11")); sllv_append(precords, lrec_literal_2("l","1", "b","12")); sllv_append(precords, lrec_literal_2("x","200", "b","13")); sllv_append(precords, lrec_literal_2("l","3", "b","14")); sllv_append(precords, lrec_literal_2("l","3", "b","15")); sllv_append(precords, lrec_literal_2("x","300", "b","16")); sllv_append(precords, lrec_literal_2("l","5", "b","17")); sllv_append(precords, lrec_literal_2("l","5", "b","18")); return precords; }
// pnode is input; pkeylist_evaluators is appended to. sllv_t* allocate_keylist_evaluators_from_ast_node( mlr_dsl_ast_node_t* pnode, fmgr_t* pfmgr, int type_inferencing, int context_flags) { sllv_t* pkeylist_evaluators = sllv_alloc(); if (pnode->pchildren != NULL) { // Non-indexed localvars have no child nodes in the AST. for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) { mlr_dsl_ast_node_t* pkeynode = pe->pvvalue; if (pkeynode->type == MD_AST_NODE_TYPE_STRING_LITERAL) { sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_string(pkeynode->text)); } else { sllv_append(pkeylist_evaluators, rval_evaluator_alloc_from_ast(pkeynode, pfmgr, type_inferencing, context_flags)); } } } return pkeylist_evaluators; }
// ---------------------------------------------------------------- ex_ast_node_t* ex_ast_tree_copy(ex_ast_node_t* pold) { ex_ast_node_t* pnew = ex_ast_node_copy(pold); if (pold->pchildren != NULL) { pnew->pchildren = sllv_alloc(); for (sllve_t* pe = pold->pchildren->phead; pe != NULL; pe = pe->pnext) { ex_ast_node_t* pchild = pe->pvvalue; sllv_append(pnew->pchildren, ex_ast_tree_copy(pchild)); } } return pnew; }
// ---------------------------------------------------------------- static sllv_t* make_records_113335() { sllv_t* precords = sllv_alloc(); sllv_append(precords, lrec_literal_2("l","1", "b","10")); sllv_append(precords, lrec_literal_2("l","1", "b","11")); sllv_append(precords, lrec_literal_2("l","3", "b","12")); sllv_append(precords, lrec_literal_2("l","3", "b","13")); sllv_append(precords, lrec_literal_2("l","3", "b","14")); sllv_append(precords, lrec_literal_2("l","5", "b","15")); return precords; }
// ---------------------------------------------------------------- static char* test_sllv_append() { mu_assert_lf(0 == 0); sllv_t* pa = sllv_alloc(); sllv_add(pa, "a"); sllv_add(pa, "b"); sllv_add(pa, "c"); mu_assert_lf(pa->length == 3); sllve_t* pe = pa->phead; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "a")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "b")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "c")); pe = pe->pnext; mu_assert_lf(pe == NULL); sllv_t* pb = sllv_alloc(); sllv_add(pb, "d"); sllv_add(pb, "e"); mu_assert_lf(pb->length == 2); pe = pb->phead; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "d")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "e")); pe = pe->pnext; mu_assert_lf(pe == NULL); pa = sllv_append(pa, pb); mu_assert_lf(pa->length == 5); mu_assert_lf(pb->length == 2); pe = pa->phead; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "a")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "b")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "c")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "d")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "e")); pe = pe->pnext; mu_assert_lf(pe == NULL); pe = pb->phead; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "d")); pe = pe->pnext; mu_assert_lf(pe != NULL); mu_assert_lf(streq(pe->pvdata, "e")); pe = pe->pnext; mu_assert_lf(pe == NULL); return NULL; }
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; } }
mlr_dsl_cst_statement_t* alloc_if_head(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode, int type_inferencing, int context_flags) { if_head_state_t* pstate = mlr_malloc_or_die(sizeof(if_head_state_t)); pstate->pif_chain_statements = sllv_alloc(); for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) { // For if and elif: // * Left subnode is the AST for the boolean expression. // * Right subnode is a list of statements to be executed if the left evaluates to true. // For else: // * Sole subnode is a list of statements to be executed. mlr_dsl_ast_node_t* pitemnode = pe->pvvalue; mlr_dsl_ast_node_t* pexprnode = NULL; mlr_dsl_ast_node_t* plistnode = NULL; if (pitemnode->pchildren->length == 2) { pexprnode = pitemnode->pchildren->phead->pvvalue; plistnode = pitemnode->pchildren->phead->pnext->pvvalue; } else { pexprnode = NULL; plistnode = pitemnode->pchildren->phead->pvvalue; } sllv_append(pstate->pif_chain_statements, alloc_if_item(pcst, pitemnode, pexprnode, plistnode, type_inferencing, context_flags) ); } mlr_dsl_cst_block_handler_t* pblock_handler = (context_flags & IN_BREAKABLE) ? mlr_dsl_cst_handle_statement_block_with_break_continue : mlr_dsl_cst_handle_statement_block; return mlr_dsl_cst_statement_valloc_with_block( pnode, handle_if_head, NULL, pblock_handler, free_if_head, pstate); }
// ---------------------------------------------------------------- mlr_dsl_cst_statement_t* alloc_conditional_block(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode, int type_inferencing, int context_flags) { conditional_block_state_t* pstate = mlr_malloc_or_die(sizeof(conditional_block_state_t)); pstate->pexpression_evaluator = NULL; // Right node is a list of statements to be executed if the left evaluates to true. mlr_dsl_ast_node_t* pleft = pnode->pchildren->phead->pvvalue; mlr_dsl_ast_node_t* pright = pnode->pchildren->phead->pnext->pvvalue; pstate->pexpression_evaluator = rval_evaluator_alloc_from_ast( pleft, pcst->pfmgr, type_inferencing, context_flags); MLR_INTERNAL_CODING_ERROR_IF(pright->subframe_var_count == MD_UNUSED_INDEX); cst_statement_block_t* pblock = cst_statement_block_alloc(pright->subframe_var_count); for (sllve_t* pe = pright->pchildren->phead; pe != NULL; pe = pe->pnext) { mlr_dsl_ast_node_t* pbody_ast_node = pe->pvvalue; mlr_dsl_cst_statement_t *pchild_statement = mlr_dsl_cst_alloc_statement(pcst, pbody_ast_node, type_inferencing, context_flags); sllv_append(pblock->pstatements, pchild_statement); } mlr_dsl_cst_block_handler_t* pblock_handler = (context_flags & IN_BREAKABLE) ? mlr_dsl_cst_handle_statement_block_with_break_continue : mlr_dsl_cst_handle_statement_block; return mlr_dsl_cst_statement_valloc_with_block( pnode, handle_conditional_block, pblock, pblock_handler, free_conditional_block, pstate); }
// ---------------------------------------------------------------- mlr_dsl_cst_statement_t* alloc_unset(mlr_dsl_cst_t* pcst, mlr_dsl_ast_node_t* pnode, int type_inferencing, int context_flags) { unset_state_t* pstate = mlr_malloc_or_die(sizeof(unset_state_t)); pstate->punset_items = sllv_alloc(); mlr_dsl_cst_statement_handler_t* pstatement_handler = handle_unset; for (sllve_t* pe = pnode->pchildren->phead; pe != NULL; pe = pe->pnext) { mlr_dsl_ast_node_t* pchild = pe->pvvalue; if (pchild->type == MD_AST_NODE_TYPE_ALL || pchild->type == MD_AST_NODE_TYPE_FULL_OOSVAR) { // The grammar allows only 'unset all', not 'unset @x, all, $y'. // So if 'all' appears at all, it's the only name. Likewise with '@*'. pstatement_handler = handle_unset_all; } else if (pchild->type == MD_AST_NODE_TYPE_FULL_SREC) { if (context_flags & IN_BEGIN_OR_END) { fprintf(stderr, "%s: unset of $-variables is not valid within begin or end blocks.\n", MLR_GLOBALS.bargv0); exit(1); } unset_item_t* punset_item = alloc_blank_unset_item(); punset_item->punset_item_handler = handle_unset_full_srec; sllv_append(pstate->punset_items, punset_item); } else if (pchild->type == MD_AST_NODE_TYPE_FIELD_NAME) { if (context_flags & IN_BEGIN_OR_END) { fprintf(stderr, "%s: unset of $-variables is not valid within begin or end blocks.\n", MLR_GLOBALS.bargv0); exit(1); } unset_item_t* punset_item = alloc_blank_unset_item(); punset_item->punset_item_handler = handle_unset_srec_field_name; punset_item->srec_field_name = pchild->text; sllv_append(pstate->punset_items, punset_item); } else if (pchild->type == MD_AST_NODE_TYPE_INDIRECT_FIELD_NAME) { if (context_flags & IN_BEGIN_OR_END) { fprintf(stderr, "%s: unset of $-variables are not valid within begin or end blocks.\n", MLR_GLOBALS.bargv0); exit(1); } unset_item_t* punset_item = alloc_blank_unset_item(); punset_item->punset_item_handler = handle_unset_indirect_srec_field_name; punset_item->psrec_field_name_evaluator = rval_evaluator_alloc_from_ast( pchild->pchildren->phead->pvvalue, pcst->pfmgr, type_inferencing, context_flags); sllv_append(pstate->punset_items, punset_item); } else if (pchild->type == MD_AST_NODE_TYPE_OOSVAR_KEYLIST) { unset_item_t* punset_item = alloc_blank_unset_item(); punset_item->punset_item_handler = handle_unset_oosvar; punset_item->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node( pchild, pcst->pfmgr, type_inferencing, context_flags); sllv_append(pstate->punset_items, punset_item); } else if (pchild->type == MD_AST_NODE_TYPE_NONINDEXED_LOCAL_VARIABLE) { MLR_INTERNAL_CODING_ERROR_IF(pchild->vardef_frame_relative_index == MD_UNUSED_INDEX); unset_item_t* punset_item = alloc_blank_unset_item(); punset_item->punset_item_handler = handle_unset_nonindexed_local_variable; punset_item->local_variable_frame_relative_index = pchild->vardef_frame_relative_index; sllv_append(pstate->punset_items, punset_item); } else if (pchild->type == MD_AST_NODE_TYPE_INDEXED_LOCAL_VARIABLE) { MLR_INTERNAL_CODING_ERROR_IF(pchild->vardef_frame_relative_index == MD_UNUSED_INDEX); unset_item_t* punset_item = alloc_blank_unset_item(); punset_item->punset_item_handler = handle_unset_indexed_local_variable; punset_item->local_variable_frame_relative_index = pchild->vardef_frame_relative_index; punset_item->pkeylist_evaluators = allocate_keylist_evaluators_from_ast_node( pchild, pcst->pfmgr, type_inferencing, context_flags); sllv_append(pstate->punset_items, punset_item); } else { MLR_INTERNAL_CODING_ERROR(); } } return mlr_dsl_cst_statement_valloc( pnode, pstatement_handler, free_unset, pstate); }
// ---------------------------------------------------------------- cli_opts_t* parse_command_line(int argc, char** argv) { cli_opts_t* popts = mlr_malloc_or_die(sizeof(cli_opts_t)); memset(popts, 0, sizeof(*popts)); popts->irs = NULL; popts->ifs = NULL; popts->ips = NULL; popts->allow_repeat_ifs = NEITHER_TRUE_NOR_FALSE; popts->allow_repeat_ips = NEITHER_TRUE_NOR_FALSE; popts->use_implicit_csv_header = FALSE; popts->headerless_csv_output = FALSE; popts->ors = NULL; popts->ofs = NULL; popts->ops = NULL; popts->right_justify_xtab_value = FALSE; popts->stack_json_output_vertically = FALSE; popts->wrap_json_output_in_outer_list = FALSE; popts->quote_json_values_always = FALSE; popts->json_flatten_separator = DEFAULT_JSON_FLATTEN_SEPARATOR; popts->ofmt = DEFAULT_OFMT; popts->oquoting = DEFAULT_OQUOTING; popts->plrec_reader = NULL; popts->plrec_writer = NULL; popts->prepipe = NULL; popts->filenames = NULL; popts->ifile_fmt = "dkvp"; popts->ofile_fmt = "dkvp"; popts->use_mmap_for_read = TRUE; int left_align_pprint = TRUE; int have_rand_seed = FALSE; unsigned rand_seed = 0; int argi = 1; for (; argi < argc; argi++) { if (argv[argi][0] != '-') { break; } else if (streq(argv[argi], "--version")) { #ifdef HAVE_CONFIG_H printf("Miller %s\n", PACKAGE_VERSION); #else printf("Miller %s\n", MLR_VERSION); #endif // HAVE_CONFIG_H exit(0); } else if (streq(argv[argi], "-h")) { main_usage(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--help")) { main_usage(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--help-all-verbs")) { usage_all_verbs(argv[0]); } else if (streq(argv[argi], "--list-all-verbs") || streq(argv[argi], "-l")) { list_all_verbs(stdout, ""); exit(0); } else if (streq(argv[argi], "--list-all-verbs-raw")) { list_all_verbs_raw(stdout); exit(0); } else if (streq(argv[argi], "--list-all-functions-raw")) { lrec_evaluator_list_all_functions_raw(stdout); exit(0); } else if (streq(argv[argi], "--help-all-functions") || streq(argv[argi], "-f")) { lrec_evaluator_function_usage(stdout, NULL); exit(0); } else if (streq(argv[argi], "--help-function") || streq(argv[argi], "--hf")) { check_arg_count(argv, argi, argc, 2); lrec_evaluator_function_usage(stdout, argv[argi+1]); exit(0); // main-usage subsections, individually accessible for the benefit of // the manpage-autogenerator } else if (streq(argv[argi], "--usage-synopsis")) { main_usage_synopsis(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-examples")) { main_usage_examples(stdout, argv[0], ""); exit(0); } else if (streq(argv[argi], "--usage-list-all-verbs")) { list_all_verbs(stdout, ""); exit(0); } else if (streq(argv[argi], "--usage-help-options")) { main_usage_help_options(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-functions")) { main_usage_functions(stdout, argv[0], ""); exit(0); } else if (streq(argv[argi], "--usage-data-format-examples")) { main_usage_data_format_examples(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-data-format-options")) { main_usage_data_format_options(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-compressed-data-options")) { main_usage_compressed_data_options(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-separator-options")) { main_usage_separator_options(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-csv-options")) { main_usage_csv_options(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-double-quoting")) { main_usage_double_quoting(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-numerical-formatting")) { main_usage_numerical_formatting(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-other-options")) { main_usage_other_options(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-then-chaining")) { main_usage_then_chaining(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--usage-see-also")) { main_usage_see_also(stdout, argv[0]); exit(0); } else if (streq(argv[argi], "--rs")) { check_arg_count(argv, argi, argc, 2); popts->ors = sep_from_arg(argv[argi+1], argv[0]); popts->irs = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--irs")) { check_arg_count(argv, argi, argc, 2); popts->irs = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--ors")) { check_arg_count(argv, argi, argc, 2); popts->ors = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--fs")) { check_arg_count(argv, argi, argc, 2); popts->ofs = sep_from_arg(argv[argi+1], argv[0]); popts->ifs = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--ifs")) { check_arg_count(argv, argi, argc, 2); popts->ifs = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--ofs")) { check_arg_count(argv, argi, argc, 2); popts->ofs = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--repifs")) { popts->allow_repeat_ifs = TRUE; } else if (streq(argv[argi], "--implicit-csv-header")) { popts->use_implicit_csv_header = TRUE; } else if (streq(argv[argi], "--headerless-csv-output")) { popts->headerless_csv_output = TRUE; } else if (streq(argv[argi], "-p")) { popts->ifile_fmt = "nidx"; popts->ofile_fmt = "nidx"; popts->ifs = " "; popts->ofs = " "; popts->allow_repeat_ifs = TRUE; } else if (streq(argv[argi], "--ps")) { check_arg_count(argv, argi, argc, 2); popts->ops = sep_from_arg(argv[argi+1], argv[0]); popts->ips = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--ips")) { check_arg_count(argv, argi, argc, 2); popts->ips = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--ops")) { check_arg_count(argv, argi, argc, 2); popts->ops = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--xvright")) { popts->right_justify_xtab_value = TRUE; } else if (streq(argv[argi], "--jvstack")) { popts->stack_json_output_vertically = TRUE; } else if (streq(argv[argi], "--jlistwrap")) { popts->wrap_json_output_in_outer_list = TRUE; } else if (streq(argv[argi], "--jquoteall")) { popts->quote_json_values_always = TRUE; } else if (streq(argv[argi], "--jflatsep")) { check_arg_count(argv, argi, argc, 2); popts->json_flatten_separator = sep_from_arg(argv[argi+1], argv[0]); argi++; } else if (streq(argv[argi], "--csv")) { popts->ifile_fmt = popts->ofile_fmt = "csv"; } else if (streq(argv[argi], "--icsv")) { popts->ifile_fmt = "csv"; } else if (streq(argv[argi], "--ocsv")) { popts->ofile_fmt = "csv"; } else if (streq(argv[argi], "--csvlite")) { popts->ifile_fmt = popts->ofile_fmt = "csvlite"; } else if (streq(argv[argi], "--icsvlite")) { popts->ifile_fmt = "csvlite"; } else if (streq(argv[argi], "--ocsvlite")) { popts->ofile_fmt = "csvlite"; } else if (streq(argv[argi], "--dkvp")) { popts->ifile_fmt = popts->ofile_fmt = "dkvp"; } else if (streq(argv[argi], "--idkvp")) { popts->ifile_fmt = "dkvp"; } else if (streq(argv[argi], "--odkvp")) { popts->ofile_fmt = "dkvp"; } else if (streq(argv[argi], "--json")) { popts->ifile_fmt = popts->ofile_fmt = "json"; } else if (streq(argv[argi], "--ijson")) { popts->ifile_fmt = "json"; } else if (streq(argv[argi], "--ojson")) { popts->ofile_fmt = "json"; } else if (streq(argv[argi], "--nidx")) { popts->ifile_fmt = popts->ofile_fmt = "nidx"; } else if (streq(argv[argi], "--inidx")) { popts->ifile_fmt = "nidx"; } else if (streq(argv[argi], "--onidx")) { popts->ofile_fmt = "nidx"; } else if (streq(argv[argi], "--xtab")) { popts->ifile_fmt = popts->ofile_fmt = "xtab"; } else if (streq(argv[argi], "--ixtab")) { popts->ifile_fmt = "xtab"; } else if (streq(argv[argi], "--oxtab")) { popts->ofile_fmt = "xtab"; } else if (streq(argv[argi], "--ipprint")) { popts->ifile_fmt = "csvlite"; popts->ifs = " "; popts->allow_repeat_ifs = TRUE; } else if (streq(argv[argi], "--opprint")) { popts->ofile_fmt = "pprint"; } else if (streq(argv[argi], "--pprint")) { popts->ifile_fmt = "csvlite"; popts->ifs = " "; popts->allow_repeat_ifs = TRUE; popts->ofile_fmt = "pprint"; } else if (streq(argv[argi], "--right")) { left_align_pprint = FALSE; } else if (streq(argv[argi], "--ofmt")) { check_arg_count(argv, argi, argc, 2); popts->ofmt = argv[argi+1]; argi++; } else if (streq(argv[argi], "--quote-all")) { popts->oquoting = QUOTE_ALL; } else if (streq(argv[argi], "--quote-none")) { popts->oquoting = QUOTE_NONE; } else if (streq(argv[argi], "--quote-minimal")) { popts->oquoting = QUOTE_MINIMAL; } else if (streq(argv[argi], "--quote-numeric")) { popts->oquoting = QUOTE_NUMERIC; } else if (streq(argv[argi], "--mmap")) { popts->use_mmap_for_read = TRUE; } else if (streq(argv[argi], "--no-mmap")) { popts->use_mmap_for_read = FALSE; } else if (streq(argv[argi], "--seed")) { check_arg_count(argv, argi, argc, 2); if (sscanf(argv[argi+1], "0x%x", &rand_seed) == 1) { have_rand_seed = TRUE; } else if (sscanf(argv[argi+1], "%u", &rand_seed) == 1) { have_rand_seed = TRUE; } else { main_usage(stderr, argv[0]); exit(1); } argi++; } else if (streq(argv[argi], "--prepipe")) { check_arg_count(argv, argi, argc, 2); popts->prepipe = argv[argi+1]; popts->use_mmap_for_read = FALSE; argi++; } else { usage_unrecognized_verb(argv[0], argv[argi]); } } lhmss_t* default_rses = get_default_rses(); lhmss_t* default_fses = get_default_fses(); lhmss_t* default_pses = get_default_pses(); lhmsi_t* default_repeat_ifses = get_default_repeat_ifses(); lhmsi_t* default_repeat_ipses = get_default_repeat_ipses(); if (popts->irs == NULL) popts->irs = lhmss_get(default_rses, popts->ifile_fmt); if (popts->ifs == NULL) popts->ifs = lhmss_get(default_fses, popts->ifile_fmt); if (popts->ips == NULL) popts->ips = lhmss_get(default_pses, popts->ifile_fmt); if (popts->allow_repeat_ifs == NEITHER_TRUE_NOR_FALSE) popts->allow_repeat_ifs = lhmsi_get(default_repeat_ifses, popts->ifile_fmt); if (popts->allow_repeat_ips == NEITHER_TRUE_NOR_FALSE) popts->allow_repeat_ips = lhmsi_get(default_repeat_ipses, popts->ifile_fmt); if (popts->ors == NULL) popts->ors = lhmss_get(default_rses, popts->ofile_fmt); if (popts->ofs == NULL) popts->ofs = lhmss_get(default_fses, popts->ofile_fmt); if (popts->ops == NULL) popts->ops = lhmss_get(default_pses, popts->ofile_fmt); if (popts->irs == NULL) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->ifs == NULL) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->ips == NULL) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->allow_repeat_ifs == NEITHER_TRUE_NOR_FALSE) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->allow_repeat_ips == NEITHER_TRUE_NOR_FALSE) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->ors == NULL) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->ofs == NULL) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (popts->ops == NULL) { fprintf(stderr, "%s: internal coding error detected in file %s at line %d.\n", argv[0], __FILE__, __LINE__); exit(1); } if (streq(popts->ofile_fmt, "pprint") && strlen(popts->ofs) != 1) { fprintf(stderr, "%s: OFS for PPRINT format must be single-character; got \"%s\".\n", argv[0], popts->ofs); return NULL; } if (streq(popts->ofile_fmt, "dkvp")) popts->plrec_writer = lrec_writer_dkvp_alloc(popts->ors, popts->ofs, popts->ops); else if (streq(popts->ofile_fmt, "json")) popts->plrec_writer = lrec_writer_json_alloc(popts->stack_json_output_vertically, popts->wrap_json_output_in_outer_list, popts->quote_json_values_always, popts->json_flatten_separator); else if (streq(popts->ofile_fmt, "csv")) popts->plrec_writer = lrec_writer_csv_alloc(popts->ors, popts->ofs, popts->oquoting, popts->headerless_csv_output); else if (streq(popts->ofile_fmt, "csvlite")) popts->plrec_writer = lrec_writer_csvlite_alloc(popts->ors, popts->ofs, popts->headerless_csv_output); else if (streq(popts->ofile_fmt, "nidx")) popts->plrec_writer = lrec_writer_nidx_alloc(popts->ors, popts->ofs); else if (streq(popts->ofile_fmt, "xtab")) popts->plrec_writer = lrec_writer_xtab_alloc(popts->ofs, popts->ops, popts->right_justify_xtab_value); else if (streq(popts->ofile_fmt, "pprint")) popts->plrec_writer = lrec_writer_pprint_alloc(popts->ors, popts->ofs[0], left_align_pprint); else { main_usage(stderr, argv[0]); exit(1); } if ((argc - argi) < 1) { main_usage(stderr, argv[0]); exit(1); } popts->pmapper_list = sllv_alloc(); while (TRUE) { check_arg_count(argv, argi, argc, 1); char* verb = argv[argi]; mapper_setup_t* pmapper_setup = look_up_mapper_setup(verb); if (pmapper_setup == NULL) { fprintf(stderr, "%s: verb \"%s\" not found. Please use \"%s --help\" for a list.\n", argv[0], verb, argv[0]); exit(1); } if ((argc - argi) >= 2) { if (streq(argv[argi+1], "-h") || streq(argv[argi+1], "--help")) { pmapper_setup->pusage_func(stdout, argv[0], verb); exit(0); } } // It's up to the parse func to print its usage on CLI-parse failure. mapper_t* pmapper = pmapper_setup->pparse_func(&argi, argc, argv); if (pmapper == NULL) { exit(1); } sllv_append(popts->pmapper_list, pmapper); if (argi >= argc || !streq(argv[argi], "then")) break; argi++; } popts->filenames = &argv[argi]; // No filenames means read from standard input, and standard input cannot be mmapped. if (argi == argc) popts->use_mmap_for_read = FALSE; popts->plrec_reader = lrec_reader_alloc(popts->ifile_fmt, popts->use_mmap_for_read, popts->irs, popts->ifs, popts->allow_repeat_ifs, popts->ips, popts->allow_repeat_ips, popts->use_implicit_csv_header, popts->json_flatten_separator); if (popts->plrec_reader == NULL) { main_usage(stderr, argv[0]); exit(1); } if (have_rand_seed) { mtrand_init(rand_seed); } else { mtrand_init_default(); } return popts; }