📄 cmdline.c
字号:
/* cmdline.c -- command line parsing routines *//* Copyright 1989 Carnegie Mellon University *//* * This module is designed to allow various modules to scan (and rescan) * the command line for applicable arguments. The goal is to hide as * much information about switches and their names as possible so that * switches become more consistent across applications and so that the * author of an application need not do a lot of work to provide numerous * options. Instead, each module scans the command line for its own * arguments. * * Command lines are of the following form: * command -s1 -s2 opt2 -s3 arg1 arg2 -s4 opt4 arg3 * Note that there are three kinds of command line parameters: * (1) A Switch is a "-" followed by a name, e.g. "-s1" * (2) An Option is a Switch followed by a space and name, e.g. "-s2 opt2" * (3) An Argument is a name by itself, e.g. "arg1" * Note also that a switch followed by an argument looks just like an * option, so a list of valid option names is necessary to disambiguate. * * Long names are good for readability, but single character abbreviations * are nice for experienced users. cmdline.c allows single character * abbreviations provided that they are unambiguous. These are * recognized with no extra work by the programmer. If an * isolated '?' is encountered in the command line, then all of * the options and switches are printed as help and for debugging. * * Given that we must tell this module about option names and switch * names, how should we do it? We can't wait until modules are * initialized, since often modules want to read the command line * at initialization time. In the original implementation, the * main program was supposed to provide names for the whole program, * but this violates modularity: when an option is added to a module, * the main program has to be modified too. This is a real pain when * different machines support different options and you want to have * a single machine-independent main program. The solution is to * have the main program import strings describing the options and * switches used by each module. These are passed into cmdline.c * before initialization of other modules is begun. * * A main program that uses cmdline.c should do the following: * call cl_syntax(s) for each module's option/switch string. * The string s should have the following format: * "opt1<o>description;opt2<o>description;...;switch1<s>description;..." * where opt1 and opt2 are option names (without the preceding "-"), and * switch1 is a switch name. The <o> and <s> indicate whether the * name is an option or a switch. The descriptions are arbitrary strings * (without semicolons) that are printed out for the user when "?" * is typed on the command line. * * After calling cl_syntax, main() should call * cl_init(argv, argc) * cl_init will report an error (to stderr) if it finds any illegal * switch or option names in argv, and help will be printed if "?" * is found in argv. If cl_init returns false, then the user has been * given an error message or help, and main should probably exit. * * Afterward, switches, options, and arguments can be accessed by * calling cl_switch, cl_option, and cl_arg. If cl_switch or cl_option * is called with a switch name that was not mentioned in the call to * cl_init, an error will result. This indicates that the application * author omitted a valid switch or option name when calling cl_init. * This is an error because the full set of names is needed for error * checking and to distinguish arguments from options. * *//****************************************************************************** Change Log* Date | Change*-----------+-----------------------------------------------------------------* 13-Jun-86 | Created Change Log* 6-Aug-86 | Modified for Lattice 3.0 -- use "void" to type some routines* 20-Sep-89 | Redesigned the interface, adding cl_syntax call.* 2-Apr-91 | JDW : further changes* 27-Dec-93 | "@file" as first arg reads command line args from file* 11-Mar-94 | PLu: Add private to cl_search() definition.* 28-Apr-03 | DM: true->TRUE, false->FALSE*****************************************************************************//* stdlib.h not on PMAX */#ifndef mips#include "stdlib.h"#endif#include "stdio.h"#include "cext.h"#include "userio.h"#include "cmdline.h"#include "ctype.h"#include "string.h"#define syntax_max 10 /* allow for 10 syntax strings */private char *syntax[syntax_max];private int n_syntax = 0; /* number of strings so far */private char **argv; /* command line argument vector */private int argc; /* length of argv */private boolean cl_rdy = FALSE; /* set to TRUE when initialized */#define cl_OPT 1#define cl_SW 2#define cl_INIT 3#define cl_ARG 4/****************************************************************************** Routines local to this module*****************************************************************************/private char *cl_search();private int find_string();private void indirect_command(char *filename, char *oldarg0);private void ready_check();/***************************************************************** cl_arg* Inputs:* n: the index of the arg needed* Results:* pointer to the nth arg, or NULL if none exists* arg 0 is the command name*****************************************************************/char *cl_arg(n) int n;{ return (n <= 0 ? argv[0] : cl_search((char *)NULL, cl_ARG, n));}/* cl_help -- print help from syntax strings *//**/void cl_help(){ register int i, j; int count = 0; /* see if there are any switches or flags */ for (i = 0; i < n_syntax; i++) { register char *ptr = syntax[i]; register char c = *ptr++; while (c != EOS) { while (c != EOS && !(isalnum(c))) c = *ptr++; if (c != EOS) { count++; gprintf(TRANS, "-"); j = 1; while (c != EOS && c != '<') { gprintf(TRANS, "%c", c); c = *ptr++; j++; } if (c != EOS) { c = *ptr++; if (c == 'o') { gprintf(TRANS, " xxx"); j += 4; } } /* attempt to tab */ do { gprintf(TRANS, " "); } while (j++ < 16); while (c != EOS && c != '>') c = *ptr++; if (c != EOS) c = *ptr++; while (c != EOS && c != ';') { gprintf(TRANS, "%c", c); c = *ptr++; } gprintf(TRANS, "\n"); } } } if (!count) gprintf(TRANS, "No switches or options exist.\n");}/****************************************************************************** cl_init* Inputs:* char *switches[]: array of switch names* int nsw: number of switch names* char *options[]: array of option names* int nopt: number of option names* char *av: array of command line fields (argv)* int ac: number of command line fields (argc)* Effect:* Checks that all command line entries are valid.* Saves info for use by other routines.* Returns:* TRUE if syntax checks OK, otherwise false*****************************************************************************/boolean cl_init(av, ac) char *av[]; int ac;{ argv = av; argc = ac; /* check for help request */ if (argc == 2 && strcmp(argv[1], "?") == 0) { cl_help(); return FALSE; /* avoid cl_search which would complain about "?" */ } /* check for indirection */ if (argc == 2 && *(argv[1]) == '@') { /* read new args from file */ indirect_command(av[1] + 1, av[0]); } /* check command line syntax: */ cl_rdy = TRUE; return (cl_rdy = (cl_search("true", cl_INIT, 0) != NULL));}/***************************************************************** cl_int_option* Inputs:* char *name: name of option* long default: default value for option* Result:* returns long encoding of the option, deflt if none* Implementation:* call cl_option and sscanf result*****************************************************************/long cl_int_option(name, deflt) char *name; long deflt;{ char *opt = cl_option(name); if (opt) { if (sscanf(opt, "%ld", &deflt) != 1) { gprintf(TRANS, "Warning: option %s %s not an integer, ignored\n", name, opt); } } return deflt;}/***************************************************************** cl_search
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -