diff options
author | midipix <writeonce@midipix.org> | 2025-05-29 00:53:15 +0000 |
---|---|---|
committer | midipix <writeonce@midipix.org> | 2025-05-29 03:35:46 +0000 |
commit | 59b920bb87eab928e77b5227a1ed9023292a7552 (patch) | |
tree | df0f396edc1cec2156f5ee7d543b39ed05e20a4b /src/driver | |
parent | bbc6acc8f263e26cd487b936ee5ab7a61b59b277 (diff) | |
download | perk-59b920bb87eab928e77b5227a1ed9023292a7552.tar.bz2 perk-59b920bb87eab928e77b5227a1ed9023292a7552.tar.xz |
driver: become multi-cmd ready, added pe_cmd_perk().
Diffstat (limited to 'src/driver')
-rw-r--r-- | src/driver/pe_amain.c | 71 | ||||
-rw-r--r-- | src/driver/pe_driver_ctx.c | 329 |
2 files changed, 259 insertions, 141 deletions
diff --git a/src/driver/pe_amain.c b/src/driver/pe_amain.c index 286e111..1804246 100644 --- a/src/driver/pe_amain.c +++ b/src/driver/pe_amain.c @@ -48,63 +48,6 @@ static ssize_t pe_version(struct pe_driver_ctx * dctx, int fdout) verclr[4],verinfo->commit,verclr[5]); } -static void pe_perform_hdrdump_actions( - const struct pe_driver_ctx * dctx, - struct pe_unit_ctx * uctx) -{ - if (dctx->cctx->hdrdump & PERK_HDRDUMP_IMAGE_DOS_HEADER) - pe_hdrdump_image_dos_hdr(dctx,uctx->meta); - - if (dctx->cctx->hdrdump & PERK_HDRDUMP_COFF_IMAGE_HEADER) - pe_hdrdump_coff_image_hdr(dctx,uctx->meta); - - if (dctx->cctx->hdrdump & PERK_HDRDUMP_COFF_OBJECT_HEADER) - pe_hdrdump_coff_object_hdr(dctx,uctx->meta); - - if (dctx->cctx->hdrdump & PERK_HDRDUMP_COFF_OPT_HEADER) - pe_hdrdump_coff_opt_hdr(dctx,uctx->meta); - - if (dctx->cctx->hdrdump & PERK_HDRDUMP_SECTION_TABLE) - pe_hdrdump_sec_tbl(dctx,uctx->meta); - - if (dctx->cctx->hdrdump & PERK_HDRDUMP_EXPORT_HEADER) - pe_hdrdump_export_hdr(dctx,uctx->meta); - - if (dctx->cctx->hdrdump & PERK_HDRDUMP_IMPORT_TABLE) - pe_hdrdump_import_tbl(dctx,uctx->meta); -} - -static void pe_perform_unit_actions( - const struct pe_driver_ctx * dctx, - struct pe_unit_ctx * uctx) -{ - uint64_t flags = dctx->cctx->fmtflags; - - if (flags & PERK_OUTPUT_IMAGE_CATEGORY) - pe_output_image_category(dctx,uctx->meta); - - if (flags & PERK_OUTPUT_IMAGE_SECTIONS) - pe_output_image_sections(dctx,uctx->meta); - - if (flags & PERK_OUTPUT_IMAGE_SYMBOLS) - pe_output_image_symbols(dctx,uctx->meta); - - if (flags & PERK_OUTPUT_IMAGE_STRINGS) - pe_output_image_strings(dctx,uctx->meta); - - if (flags & PERK_OUTPUT_EXPORT_SYMS) - pe_output_export_symbols(dctx,uctx->meta); - - if ((flags & PERK_OUTPUT_IMPORT_LIBS) || (flags & PERK_OUTPUT_IMPORT_SYMS)) - pe_output_import_libraries(dctx,uctx->meta); - - if ((flags & PERK_OUTPUT_MDSO_LIBS) || (flags & PERK_OUTPUT_MDSO_SYMS)) - pe_output_mdso_libraries(dctx,uctx->meta); - - if (dctx->cctx->hdrdump) - pe_perform_hdrdump_actions(dctx,uctx); -} - static int pe_exit(struct pe_driver_ctx * dctx, int ret) { pe_output_error_vector(dctx); @@ -118,7 +61,6 @@ int pe_main(char ** argv, char ** envp, const struct pe_fd_ctx * fdctx) int fdout; uint64_t flags; struct pe_driver_ctx * dctx; - struct pe_unit_ctx * uctx; const char ** unit; flags = PERK_DRIVER_FLAGS; @@ -133,11 +75,14 @@ int pe_main(char ** argv, char ** envp, const struct pe_fd_ctx * fdctx) if ((pe_version(dctx,fdout)) < 0) return pe_exit(dctx,PERK_ERROR); - for (unit=dctx->units; *unit; unit++) { - if (!(pe_get_unit_ctx(dctx,*unit,&uctx))) { - pe_perform_unit_actions(dctx,uctx); - pe_free_unit_ctx(uctx); - } + switch (dctx->cctx->cmd) { + case PERK_CMD_PERK: + for (unit=dctx->units; *unit; unit++) + pe_cmd_perk(dctx,*unit); + break; + + default: + break; } return pe_exit(dctx,dctx->errv[0] ? PERK_ERROR : PERK_OK); diff --git a/src/driver/pe_driver_ctx.c b/src/driver/pe_driver_ctx.c index 9955548..04483eb 100644 --- a/src/driver/pe_driver_ctx.c +++ b/src/driver/pe_driver_ctx.c @@ -24,6 +24,17 @@ static const struct pe_source_version pe_src_version = { PERK_GIT_VERSION }; +/* perk command names */ +static const char * const perk_cmd_name[PERK_CMD_CAP] = { + [PERK_CMD_PERK] = "perk", +}; + +/* perk command options */ +static const struct argv_option * perk_cmd_options[PERK_CMD_CAP] = { + [PERK_CMD_DEFAULT] = pe_default_options, + [PERK_CMD_PERK] = pe_perk_options, +}; + /* default fd context */ static const struct pe_fd_ctx pe_default_fdctx = { .fdin = STDIN_FILENO, @@ -62,13 +73,30 @@ static int pe_driver_usage( const char * program, const char * arg, const struct argv_option ** optv, - struct argv_meta * meta) + struct argv_meta * meta, + enum pe_cmd cmd) { - char header[512]; + char header[512]; + char * cmdarg[2]; + const char * cmdname; + + if (cmd == PERK_CMD_DEFAULT) { + cmdarg[0] = ""; + cmdarg[1] = ""; + cmdname = ""; + } else { + cmdarg[0] = " (--cmd="; + cmdarg[1] = ")"; + cmdname = perk_cmd_name[cmd]; + } snprintf(header,sizeof(header), - "Usage: %s [options] <file>...\n" "Options:\n", - program); + "Usage: %s [options] ...\n" + "Usage: %s [options] [--cmd=<command>] <arg> <arg> ...\n\n" + "Notes: --cmd must precede all non-option arguments, as well as\n" + " all arguments that are specific to the selected command.\n\n" + "Options%s%s%s:\n", + program,program,cmdarg[0],cmdname,cmdarg[1]); argv_usage(fdout,header,optv,arg); argv_free(meta); @@ -113,52 +141,43 @@ static struct pe_driver_ctx_impl * pe_driver_ctx_alloc( return &ictx->ctx; } -static int pe_get_driver_ctx_fail(struct argv_meta * meta) -{ - argv_free(meta); - return -1; -} - -int pe_get_driver_ctx( - char ** argv, - char ** envp, - uint32_t flags, - const struct pe_fd_ctx * fdctx, - struct pe_driver_ctx ** pctx) +static int pe_cmd_from_program(const char * program) { - struct pe_driver_ctx_impl * ctx; - struct pe_common_ctx cctx; - const struct argv_option * optv[PERK_OPTV_ELEMENTS]; - struct argv_meta * meta; - struct argv_entry * entry; - size_t nunits; - const char * program; - const char * pretty; + const char * dot; + const char * hyphen; + const char * mark; - (void)envp; + dot = strrchr(program,'.'); + hyphen = strrchr(program,'-'); - if (!fdctx) - fdctx = &pe_default_fdctx; + if (hyphen > dot) + mark = ++hyphen; + else if (dot > hyphen) + mark = ++dot; + else + mark = program; - argv_optv_init(pe_default_options,optv); + if (!strcmp(mark,"perk")) { + return PERK_CMD_PERK; - if (!(meta = argv_get( - argv,optv, - pe_argv_flags(flags), - fdctx->fderr))) - return -1; + } else { + return PERK_CMD_DEFAULT; + } +} - pretty = 0; - nunits = 0; - program = argv_program_name(argv[0]); - memset(&cctx,0,sizeof(cctx)); - cctx.drvflags = flags; +static int pe_cctx_update( + const char * program, + const struct argv_option ** optv, + struct argv_meta * meta, + uint32_t flags, + const struct pe_fd_ctx * fdctx, + struct pe_common_ctx * cctx, + size_t * nunits) +{ + struct argv_entry * entry; + const char * pretty; - if (!argv[1] && (flags & PERK_DRIVER_VERBOSITY_USAGE)) - return pe_driver_usage( - fdctx->fderr, - program, - 0,optv,meta); + pretty = 0; /* get options, count units */ for (entry=meta->entries; entry->fopt || entry->arg; entry++) { @@ -169,11 +188,21 @@ int pe_get_driver_ctx( return pe_driver_usage( fdctx->fdout, program,entry->arg, - optv,meta); + optv,0,cctx->cmd); + break; + + case TAG_CMD: + if (*nunits) + return pe_driver_usage( + fdctx->fderr, + program,0, + optv,0,cctx->cmd); + + cctx->cmd = pe_cmd_from_program(entry->arg); break; case TAG_VERSION: - cctx.drvflags |= PERK_DRIVER_VERSION; + cctx->drvflags |= PERK_DRIVER_VERSION; break; case TAG_PRETTY: @@ -181,86 +210,230 @@ int pe_get_driver_ctx( break; case TAG_CATEGORY: - cctx.fmtflags |= PERK_OUTPUT_IMAGE_CATEGORY; + cctx->fmtflags |= PERK_OUTPUT_IMAGE_CATEGORY; break; case TAG_SECTIONS: - cctx.fmtflags |= PERK_OUTPUT_IMAGE_SECTIONS; + cctx->fmtflags |= PERK_OUTPUT_IMAGE_SECTIONS; break; case TAG_SYMBOLS: - cctx.fmtflags |= PERK_OUTPUT_IMAGE_SYMBOLS; + cctx->fmtflags |= PERK_OUTPUT_IMAGE_SYMBOLS; break; case TAG_STRINGS: - cctx.fmtflags |= PERK_OUTPUT_IMAGE_STRINGS; + cctx->fmtflags |= PERK_OUTPUT_IMAGE_STRINGS; break; case TAG_EXPSYMS: - cctx.fmtflags |= PERK_OUTPUT_EXPORT_SYMS; + cctx->fmtflags |= PERK_OUTPUT_EXPORT_SYMS; break; case TAG_IMPLIBS: - cctx.fmtflags |= PERK_OUTPUT_IMPORT_LIBS; + cctx->fmtflags |= PERK_OUTPUT_IMPORT_LIBS; break; case TAG_IMPSYMS: - cctx.fmtflags |= PERK_OUTPUT_IMPORT_SYMS; + cctx->fmtflags |= PERK_OUTPUT_IMPORT_SYMS; break; case TAG_DSOLIBS: - cctx.fmtflags |= PERK_OUTPUT_MDSO_LIBS; + cctx->fmtflags |= PERK_OUTPUT_MDSO_LIBS; break; case TAG_DSOSYMS: - cctx.fmtflags |= PERK_OUTPUT_MDSO_SYMS; + cctx->fmtflags |= PERK_OUTPUT_MDSO_SYMS; break; case TAG_HDRDUMP: if (!entry->arg) { - cctx.hdrdump = 0; - cctx.hdrdump = ~cctx.hdrdump; + cctx->hdrdump = 0; + cctx->hdrdump = ~cctx->hdrdump; } else if (!strcmp(entry->arg,"dos")) { - cctx.hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER; + cctx->hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER; } else if (!strcmp(entry->arg,"image.dos")) { - cctx.hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER; + cctx->hdrdump = PERK_HDRDUMP_IMAGE_DOS_HEADER; } else if (!strcmp(entry->arg,"coff")) { - cctx.hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER; - cctx.hdrdump |= PERK_HDRDUMP_COFF_OBJECT_HEADER; - cctx.hdrdump |= PERK_HDRDUMP_COFF_OPT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER; + cctx->hdrdump |= PERK_HDRDUMP_COFF_OBJECT_HEADER; + cctx->hdrdump |= PERK_HDRDUMP_COFF_OPT_HEADER; } else if (!strcmp(entry->arg,"coff.image")) { - cctx.hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER; + cctx->hdrdump = PERK_HDRDUMP_COFF_IMAGE_HEADER; } else if (!strcmp(entry->arg,"coff.obj")) { - cctx.hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER; } else if (!strcmp(entry->arg,"coff.object")) { - cctx.hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_COFF_OBJECT_HEADER; } else if (!strcmp(entry->arg,"coff.opt")) { - cctx.hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER; } else if (!strcmp(entry->arg,"coff.optional")) { - cctx.hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_COFF_OPT_HEADER; } else if (!strcmp(entry->arg,"sectbl")) { - cctx.hdrdump = PERK_HDRDUMP_SECTION_TABLE; + cctx->hdrdump = PERK_HDRDUMP_SECTION_TABLE; } else if (!strcmp(entry->arg,"section.table")) { - cctx.hdrdump = PERK_HDRDUMP_SECTION_TABLE; + cctx->hdrdump = PERK_HDRDUMP_SECTION_TABLE; } else if (!strcmp(entry->arg,"exphdr")) { - cctx.hdrdump = PERK_HDRDUMP_EXPORT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_EXPORT_HEADER; } else if (!strcmp(entry->arg,"export.header")) { - cctx.hdrdump = PERK_HDRDUMP_EXPORT_HEADER; + cctx->hdrdump = PERK_HDRDUMP_EXPORT_HEADER; } else if (!strcmp(entry->arg,"imptbl")) { - cctx.hdrdump = PERK_HDRDUMP_IMPORT_TABLE; + cctx->hdrdump = PERK_HDRDUMP_IMPORT_TABLE; } else if (!strcmp(entry->arg,"import.table")) { - cctx.hdrdump = PERK_HDRDUMP_IMPORT_TABLE; + cctx->hdrdump = PERK_HDRDUMP_IMPORT_TABLE; } break; } - } else - nunits++; + } else { + (*nunits)++; + } + } + + if (pretty && !strcmp(pretty,"yaml")) { + cctx->fmtflags |= PERK_PRETTY_YAML; + + } else if (pretty && !strcmp(pretty,"dlltool")) { + cctx->fmtflags |= PERK_PRETTY_DLLTOOL; + } + + return 0; +} + +static int pe_get_driver_ctx_fail(struct argv_meta * meta) +{ + argv_free(meta); + return -1; +} + +int pe_get_driver_ctx( + char ** argv, + char ** envp, + uint32_t flags, + const struct pe_fd_ctx * fdctx, + struct pe_driver_ctx ** pctx) +{ + struct pe_driver_ctx_impl * ctx; + struct pe_common_ctx cctx; + const struct argv_option * optv[PERK_OPTV_ELEMENTS]; + struct argv_meta * meta; + size_t nunits; + const char * program; + char ** parg; + char ** pargcap; + char ** cmdargv; + char * cmdmark; + struct argv_ctx actx = {ARGV_VERBOSITY_NONE, + ARGV_MODE_SCAN, + 0,0,0,0,0,0,0,0}; + + + (void)envp; + + /* fdctx */ + if (!fdctx) + fdctx = &pe_default_fdctx; + + /* cctx */ + memset(&cctx,0,sizeof(cctx)); + + program = argv_program_name(argv[0]);\ + cctx.cmd = pe_cmd_from_program(program); + cctx.drvflags = flags; + nunits = 0; + + /* missing arguments? */ + argv_optv_init(perk_cmd_options[cctx.cmd],optv); + + if (!argv[1] && (flags & PERK_DRIVER_VERBOSITY_USAGE)) + return pe_driver_usage( + fdctx->fderr, + program,0, + optv,0,cctx.cmd); + + /* initial argv scan: ... --cmd=xxx ... */ + argv_scan(argv,optv,&actx,0); + + /* position of last base perk argument */ + if (actx.erridx && actx.unitidx) + pargcap = &argv[actx.unitidx]; + + else if (actx.erridx) + pargcap = &argv[actx.erridx]; + + else + for (pargcap=argv; *pargcap; pargcap++) + (void)0; + + /* scan for --cmd */ + for (parg=argv, cmdargv=0; (parg<pargcap) && !cmdargv; parg++) { + if (!strcmp(*parg,"--cmd") && parg[1]) { + cmdargv = &parg[2]; + cmdmark = parg[2]; + } else if (!strncmp(*parg,"--cmd=",6)) { + cmdargv = &parg[1]; + cmdmark = parg[1]; + } + } + + /* invalid perk arguments? */ + if (!actx.erridx) { + (void)0; + + } else if (&argv[actx.erridx] >= cmdargv) { + (void)0; + + } else { + if (flags & PERK_DRIVER_VERBOSITY_ERRORS) + argv_get( + argv,optv, + ARGV_VERBOSITY_ERRORS, + fdctx->fderr); + return -1; + } + + /* process argv entries preceding --cmd */ + if (cmdargv) { + *cmdargv = 0; + + if (!(meta = argv_get( + argv,optv, + pe_argv_flags(flags), + fdctx->fderr))) + return -1; + + if (pe_cctx_update( + program,optv,meta,flags, + fdctx,&cctx,&nunits)) { + argv_free(meta); + return -1; + } + + argv_free(meta); + + *cmdargv-- = cmdmark; + *cmdargv = argv[0]; + argv = cmdargv; } - if (pretty && !strcmp(pretty,"yaml")) - cctx.fmtflags |= PERK_PRETTY_YAML; - else if (pretty && !strcmp(pretty,"dlltool")) - cctx.fmtflags |= PERK_PRETTY_DLLTOOL; + /* set option vector by command */ + if (cctx.cmd == PERK_CMD_DEFAULT) { + argv_optv_init(pe_default_options,optv); + + } else if (cctx.cmd == PERK_CMD_PERK) { + argv_optv_init(pe_perk_options,optv); + } + + /* process the selected tool's command-line arguments */ + if (!(meta = argv_get( + argv,optv, + pe_argv_flags(flags), + fdctx->fderr))) + return -1; + + if (pe_cctx_update( + program,optv,meta,flags, + fdctx,&cctx,&nunits)) { + argv_free(meta); + return -1; + } if (!(ctx = pe_driver_ctx_alloc(meta,fdctx,&cctx,nunits))) return pe_get_driver_ctx_fail(meta); |