From 9a2f1f14c18532e79bb8f0a003eb43256d7e7677 Mon Sep 17 00:00:00 2001 From: Erik Nyquist Date: Sat, 21 Oct 2023 14:00:02 -0700 Subject: [PATCH] C support working --- duckargs/__init__.py | 84 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 78 insertions(+), 6 deletions(-) diff --git a/duckargs/__init__.py b/duckargs/__init__.py index 7fa01d6..7f16d7d 100644 --- a/duckargs/__init__.py +++ b/duckargs/__init__.py @@ -33,6 +33,12 @@ def main(): int main(int argc, char *argv[]) {{ + if (argc < 2) + {{ + print_usage(); + return -1; + }} + int ret = parse_args(argc, argv); if (0 != ret) {{ @@ -414,6 +420,19 @@ def _generate_c_getopt_code(processed_args, getopt_string, opts, positionals, ha if positionals: # Has both positionals and opts + ret += f" if (argc < (optind + {len(positionals)}))\n" + ret += f" {{\n" + ret += f" printf(\"Missing positional arguments\\n\");\n" + ret += f" return -1;\n" + ret += f" }}\n\n" + + for i in range(len(positionals)): + arg = positionals[i] + desc = f"Positional argument #{i + 1} ({arg.var_name})" + optarg = f"argv[optind]" + ret += '\n'.join([" " + x for x in _generate_c_opt_lines(arg, desc, optarg)]) + ret += "\n optind++;\n\n" + pass elif positionals: @@ -462,26 +481,68 @@ def _generate_c_print_code(processed_args): def _generate_c_usage_code(processed_args): lines = [] positionals = [] - has_opts = False + opts = [] for arg in processed_args: if arg.is_positional(): positionals.append(arg) - continue else: - has_opts = True + opts.append(arg) + + lines.append("") line = "program_name" - if has_opts: + if opts: line += " [OPTIONS]" if positionals: positional_names = ' '.join([x.var_name for x in positionals]) line += f" {positional_names}" - lines.append(line + "\\n\\n") + lines.append(line + "\\n") + + if opts: + longest_left_col = 0 + usage_lines = [] + + for opt in opts: + left_col = opt.opt + if opt.longopt is not None: + left_col += " " + opt.longopt + + arg = None + right_col = "" + if opt.is_flag(): + right_col = "A flag" + else: + if ArgType.INT == opt.type: + right_col = "An int value" + arg = " [int]" + elif ArgType.FLOAT == opt.type: + right_col = "A float value" + arg = " [float]" + elif ArgType.STRING == opt.type: + right_col = "A string value" + arg = " [string]" + elif ArgType.FILE == opt.type: + right_col = "A filename" + arg = " FILE" + + if arg is not None: + left_col += arg + + if len(left_col) > longest_left_col: + longest_left_col = len(left_col) - return '\n'.join([f" printf(\"{line}\");" for line in lines]) + usage_lines.append((left_col, right_col)) + + for leftcol, rightcol in usage_lines: + num_spaces = (longest_left_col + 2) - len(leftcol) + lines.append(leftcol + (" " * num_spaces) + rightcol) + + lines.append("") + + return '\n'.join([f" printf(\"{line}\\n\");" for line in lines]) def generate_c_code(argv=sys.argv): """ @@ -548,6 +609,17 @@ def generate_c_code(argv=sys.argv): decls += "\n {NULL, 0, NULL, 0}\n};\n" comment_header = "" + env_comment = os.environ.get("DUCKARGS_COMMENT", 1) + try: + env_comment_int = int(env_comment) + except ValueError: + raise RuntimeError("DUCKARGS_COMMENT must be an integer") + + if env_comment_int > 0: + comment_header = (f"// Generated by duckargs, invoked with the following arguments:\n// " + + ' '.join(argv[1:]) + "\n\n") + + CmdlineOpt.positional_count = 0 if has_flags: comment_header += "#include \n"