--- a/lib/cli/main.cc Sun Jan 20 00:12:17 2008 +0100
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,342 +0,0 @@
-// Copyright (C) 1999,2000 Bruce Guenter <bruceg@em.ca>
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 2 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#include <config.h>
-#include "ac/time.h"
-#include "fdbuf/fdbuf.h"
-#include <stdlib.h>
-#include <string.h>
-#include "cli.h"
-
-#ifndef HAVE_SRANDOM
-void srandom(unsigned int seed);
-#endif
-
-static bool do_show_usage = false;
-const char* argv0;
-const char* argv0base;
-const char* argv0dir;
-
-static cli_option help_option = { 'h', "help", cli_option::flag,
- true, &do_show_usage,
- "Display this help and exit", 0 };
-
-static cli_option** options;
-static unsigned optionc;
-
-static void build_options()
-{
- for(optionc = 0;
- cli_options[optionc].ch || cli_options[optionc].name;
- optionc++) ;
- optionc++;
- options = new cli_option*[optionc];
- for(unsigned i = 0; i < optionc-1; i++)
- options[i] = &cli_options[i];
- options[optionc-1] = &help_option;
-}
-
-static inline unsigned max(unsigned a, unsigned b)
-{
- return (a>b) ? a : b;
-}
-
-static const char* fill(unsigned i)
-{
- static unsigned lastlen = 0;
- static char* buf = 0;
- if(i > lastlen) {
- delete[] buf;
- buf = new char[i+1];
- lastlen = i;
- }
- memset(buf, ' ', i);
- buf[i] = 0;
- return buf;
-}
-
-static void show_usage()
-{
- fout << "usage: " << cli_program << " [flags] " << cli_args_usage << endl;
-}
-
-static unsigned calc_max_width()
-{
- // maxwidth is the maximum width of the long argument
- unsigned maxwidth = 0;
- for(unsigned i = 0; i < optionc; i++) {
- unsigned width = 0;
- cli_option* o = options[i];
- if(o->name) {
- width += strlen(o->name);
- switch(o->type) {
- case cli_option::string: width += 6; break;
- case cli_option::integer: width += 4; break;
- case cli_option::uinteger: width += 4; break;
- case cli_option::stringlist: width += 5; break;
- case cli_option::flag: break;
- case cli_option::counter: break;
- }
- }
- if(width > maxwidth)
- maxwidth = width;
- }
- return maxwidth;
-}
-
-static void show_option(cli_option* o, unsigned maxwidth)
-{
- if(o == &help_option)
- fout << '\n';
- if(o->ch)
- fout << " -" << o->ch;
- else
- fout << " ";
- fout << (o->ch && o->name ? ", " : " ");
- if(o->name) {
- const char* extra = "";
- switch(o->type) {
- case cli_option::string: extra = "=VALUE"; break;
- case cli_option::integer: extra = "=INT"; break;
- case cli_option::uinteger: extra = "=UNS"; break;
- case cli_option::stringlist: extra = "=ITEM"; break;
- case cli_option::flag: break;
- case cli_option::counter: break;
- }
- fout << "--" << o->name << extra
- << fill(maxwidth - strlen(o->name) - strlen(extra) + 2);
- }
- else
- fout << fill(maxwidth+4);
- fout << o->helpstr << '\n';
- if(o->defaultstr)
- fout << fill(maxwidth+10) << "(Defaults to " << o->defaultstr << ")\n";
-}
-
-static void show_help()
-{
- if(cli_help_prefix)
- fout << cli_help_prefix;
- unsigned maxwidth = calc_max_width();
- for(unsigned i = 0; i < optionc; i++)
- show_option(options[i], maxwidth);
- if(cli_help_suffix)
- fout << cli_help_suffix;
-}
-
-void usage(int exit_value, const char* errorstr)
-{
- if(errorstr)
- ferr << cli_program << ": " << errorstr << endl;
- show_usage();
- show_help();
- exit(exit_value);
-}
-
-cli_stringlist* stringlist_append(cli_stringlist* node, const char* newstr)
-{
- cli_stringlist* newnode = new cli_stringlist(newstr);
- if(node) {
- cli_stringlist* head = node;
- while(node->next)
- node = node->next;
- node->next = newnode;
- return head;
- }
- else
- return newnode;
-}
-
-int cli_option::set(const char* arg)
-{
- char* endptr;
- switch(type) {
- case flag:
- *(int*)dataptr = flag_value;
- return 0;
- case counter:
- *(int*)dataptr += flag_value;
- return 0;
- case integer:
- *(int*)dataptr = strtol(arg, &endptr, 10);
- if(*endptr) {
- ferr << argv0 << ": invalid integer: " << arg << endl;
- return -1;
- }
- return 1;
- case uinteger:
- *(unsigned*)dataptr = strtoul(arg, &endptr, 10);
- if(*endptr) {
- ferr << argv0 << ": invalid unsigned integer: " << arg << endl;
- return -1;
- }
- return 1;
- case stringlist:
- *(cli_stringlist**)dataptr =
- stringlist_append(*(cli_stringlist**)dataptr, arg);
- return 1;
- default: // string
- *(const char**)dataptr = arg;
- return 1;
- }
-}
-
-static int parse_short(int argc, char* argv[])
-{
- int end = strlen(argv[0]) - 1;
- for(int i = 1; i <= end; i++) {
- int ch = argv[0][i];
- unsigned j;
- for(j = 0; j < optionc; j++) {
- cli_option* o = options[j];
- if(o->ch == ch) {
- if(o->type != cli_option::flag &&
- o->type != cli_option::counter) {
- if(i < end) {
- if(o->set(argv[0]+i+1) != -1)
- return 0;
- }
- else if(argc <= 1) {
- ferr << argv0 << ": option -" << o->ch
- << " requires a value." << endl;
- }
- else
- if(o->set(argv[1]) != -1)
- return 1;
- }
- else if(o->set(0) != -1)
- break;
- return -1;
- }
- }
- if(j >= optionc) {
- ferr << argv0 << ": unknown option letter -" << argv[0][i] << endl;
- return -1;
- }
- }
- return 0;
-}
-
-int cli_option::parse_long_eq(const char* arg)
-{
- if(type == flag || type == counter) {
- ferr << argv0 << ": option --" << name
- << " does not take a value." << endl;
- return -1;
- }
- else
- return set(arg)-1;
-}
-
-int cli_option::parse_long_noeq(const char* arg)
-{
- if(type == flag || type == counter)
- return set(0);
- else if(arg)
- return set(arg);
- else {
- ferr << argv0 << ": option --" << name
- << " requires a value." << endl;
- return -1;
- }
-}
-
-static int parse_long(int, char* argv[])
-{
- const char* arg = argv[0]+2;
- for(unsigned j = 0; j < optionc; j++) {
- cli_option* o = options[j];
- if(o->name) {
- size_t len = strlen(o->name);
- if(!memcmp(arg, o->name, len)) {
- if(arg[len] == '\0')
- return o->parse_long_noeq(argv[1]);
- else if(arg[len] == '=')
- return o->parse_long_eq(arg+len+1);
- }
- }
- }
- ferr << argv0 << ": unknown option string: '--" << arg << "'" << endl;
- return -1;
-}
-
-static int parse_args(int argc, char* argv[])
-{
- build_options();
- int i;
- for(i = 1; i < argc; i++) {
- const char* arg = argv[i];
- // Stop at the first non-option argument
- if(arg[0] != '-')
- break;
- // Stop after the first "-" or "--"
- if(arg[1] == '\0' ||
- (arg[1] == '-' && arg[2] == '\0')) {
- i++;
- break;
- }
- int j = (arg[1] != '-') ?
- parse_short(argc-i, argv+i) :
- parse_long(argc-i, argv+i);
- if(j < 0)
- usage(1);
- else
- i += j;
- }
- return i;
-}
-
-static void set_argv0(const char* p)
-{
- argv0 = p;
- static const char* empty = "";
- const char* s = strrchr(p, '/');
- if(s) {
- ++s;
- argv0base = s;
- size_t length = s-p;
- char* tmp = new char[length+1];
- memcpy(tmp, p, length);
- tmp[length] = 0;
- argv0dir = tmp;
- }
- else {
- argv0base = p;
- argv0dir = empty;
- }
-}
-
-int main(int argc, char* argv[])
-{
- struct timeval tv;
- gettimeofday(&tv, 0);
- srandom(tv.tv_usec ^ tv.tv_sec);
-
- set_argv0(argv[0]);
- int lastarg = parse_args(argc, argv);
-
- if(do_show_usage)
- usage(0);
-
- argc -= lastarg;
- argv += lastarg;
- if(argc < cli_args_min)
- usage(1, "Too few command-line arguments");
- if(cli_args_max >= cli_args_min && argc > cli_args_max)
- usage(1, "Too many command-line arguments");
-
- return cli_main(argc, argv);
-}