Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source libSC Args Args.c
Document Actions

Args.c

by Michael L Powell last modified 2007-01-26 03:23

Click here to get the file

Size 7.7 kB - File type text/plain

File contents

/*ident	"@(#)Args:Args.c	3.1" */
/******************************************************************************
*
* C++ Standard Components, Release 3.0.
*
* Copyright (c) 1991, 1992 AT&T and Unix System Laboratories, Inc.
* Copyright (c) 1988, 1989, 1990 AT&T.  All Rights Reserved.
*
* THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T and Unix System
* Laboratories, Inc.  The copyright notice above does not evidence
* any actual or intended publication of such source code.
*
******************************************************************************/

#include "Argslib.h"

Args::Args(int argc, const char*const* argv, const char* optstr_, int bits, const char*const* keywords) :
	opterr(0),
	firstopt(0),
	lastopt(0),
	firstarg(0),
	lastarg(0),
	optstr(optstr_),
	progname_(argv[0]),
	nargs_(0),
	plus(bits & plusoptions) {
	parse(argc, argv, bits & intermix, keywords);
}

int
Args::isflag(char c) const {
	return (c == '-' || (plus && c == '+'));
}

void
Args::parse(int argc, const char*const* argv, int mix, const char*const* keywords) {
	int i;
	for (i = 1; i < argc; ++i) {
		const char* ap = argv[i];
		if (strcmp(ap, "--") == 0) {
			++i;
			break;
		}
		if (isflag(*ap))
			parse_block(argc, argv, i, keywords);
		else if (mix)
			addarg(argv[i]);
		else
			break;
	}
	for (; i < argc; ++i) {
		addarg(argv[i]);
	}
}

Args::~Args() {
	for (Opt* opt = firstopt; opt != 0; ) {
		Opt* next = opt->next;
		delete opt;
		opt = next;
	}
	for (Arg* arg = firstarg; arg != 0; ) {
		Arg* next = arg->next;
		delete arg;
		arg = next;
	}
	firstopt = lastopt = 0;
	firstarg = lastarg = 0;
	nargs_ = 0;
}

Subopt::Subopt(const char* n, const char* v) :
	name_(n),
	value_(v),
	next(0),
	prev(0) {
}

void
Args::addarg(const char* p) {
	++nargs_;
	Arg* arg = new Arg(p);
	if (lastarg == 0) {
		assert(firstarg == 0);
		firstarg = arg;
	}
	else {
		lastarg->next = arg;
	}
	lastarg = arg;
}

void
Args::addopt_(Opt* opt) {
	opt->prev = lastopt;
	if (lastopt == 0) {
		assert(firstopt == 0);
		firstopt = opt;
	}
	else {
		lastopt->next = opt;
	}
	lastopt = opt;
}

void 
Args::addopt(char flag, const char* option, const char* value, int iskey) {
	if (iskey)
		addopt_(new Opt(flag, option, value));
	else
		addopt_(new Opt(flag, *option, value));
}

// warning: name and value might not yet be null terminated
// (but they will eventually be by the caller)
void
Opt::addsubopt(char* name, char* value) {
	Subopt* subopt = new Subopt(name, value);
	subopt->prev = lastsubopt;
	if (lastsubopt == 0) {
		assert(firstsubopt == 0);
		firstsubopt = subopt;
	}
	else {
		lastsubopt->next = subopt;
	}
	lastsubopt = subopt;
}

Args::Opttype
Args::opttype(char flag, char option) {
	const char* p = strchr(optstr, option);
	if (p == 0) {
		unexpected_opt_err(flag, option);
		return illegalopt;
	}
	else {
		switch (p[1]) {
		case valchar:	return valueopt;
		case subchar:	return suboptionsopt;
		default:	return simpleopt;
		}
	}
}

// gets the value for option at ap in argv[i]
// increments i if the value is argv[i+1]
const char*
Args::getvalue(int argc, const char*const* argv, int& i, char flag, const char* ap, int iskey) {
	if (!iskey && ap[1] != nul) {
		return ap+1;
	}
	else {
		if (++i >= argc) {
			missing_val_err(flag, ap, iskey);
			return 0;
		}
		const char* value = argv[i];
		assert(value != 0);
		if (isflag(*value))
			opt_as_val_err(value);
		return value;
	}
}

static char
scanto(char*& p, const char* chars) {
	char* first = strpbrk(p, chars);
	if (first == 0)
		p += strlen(p);
	else
		p = first;
	return *p;
}

// build this option's suboptions from its value
void
Opt::build_subopts() {
	buf = new char [strlen(value_) + 1];
	strcpy(buf, value_);
	for (char* p = buf; *p != nul; ) {
		char* name = p;
		char* subvalue;
		switch (scanto(p, ",=")) {
		case ',': 
			addsubopt(name, p);
			*p++ = nul;
			break;
		case nul:
			addsubopt(name, p);
			break;
		case '=':
			*p++ = nul;
			subvalue = p;
			scanto(p, ",");
			addsubopt(name, subvalue);
			if (*p == ',') {
				*p++ = nul;
			}
			break;
		}
	}
}

void
Args::process_option(int argc, const char*const* argv, int& i, char flag, const char* ap, Opttype ot, int iskey) {
	assert(ot != illegalopt);
	if (ot == simpleopt) {
		addopt(flag, ap, 0, iskey);
	}
	else {
		const char* value = getvalue(argc, argv, i, flag, ap, iskey);
		if (value != 0) {
			addopt(flag, ap, value, iskey);
			if (ot == suboptionsopt)
				lastopt->build_subopts();
		}
	}
}

int 
Args::iskeyword_option(const char* opt, const char*const* keywords, Opttype& ot) {
	if (keywords == 0)
		return 0;
	int len = strlen(opt);
	assert(len > 0);
	int i = 0;
	const char* p;
	while ((p = keywords[i++]) != 0) {
		if (memcmp(opt, p, len) == 0) {
			switch(p[len]) {
			default:
				break;
			case nul:
				if (p[len-1] != valchar && p[len-1] != subchar) {
					ot = simpleopt;
					return 1;
				}
				break;
			case valchar:
				if (p[len+1] == nul) {
					ot = valueopt;
					return 1;
				}
				break;
			case subchar:
				if (p[len+1] == nul) {
					ot = suboptionsopt;
					return 1;
				}
				break;
			}
		}
	}
	return 0;
}

// parse argv[i]
// increments i if argv[i+1] was an option value
void
Args::parse_block(int argc, const char*const* argv, int& i, const char*const* keywords) {
	Opttype ot;
	const char* ap = argv[i];
	char flag = *ap++;
	if (*ap == nul)
		missing_opt_err();
	else if (iskeyword_option(ap, keywords, ot))
		process_option(argc, argv, i, flag, ap, ot, 1);
	else
		crack_block(argc, argv, i, flag, ap);
}

void
Args::crack_block(int argc, const char*const* argv, int& i, char flag, const char* ap) {
	for (; *ap != nul; ++ap) {
		Opttype ot = opttype(flag, *ap);;
		if (ot) {
			if (ot != simpleopt && ap > argv[i]+1) {
				// value-taking options cannot appear in option blocks
				missing_val_err(flag, ap, 0);
			}
			else {
				process_option(argc, argv, i, flag, ap, ot, 0);
				if (ot != simpleopt)
					return;
			}
		}
	}
}
		
///////////////////////
// put here to overcome
// cfront ={0} bug
//
Objection Args::unexpected_opt;
Objection Args::missing_val;
Objection Args::missing_opt;
Objection Args::opt_as_val;
//
///////////////////////

#if 0

#include <stream.h>
ostream& operator<<(ostream& os, const Args& a) {
	os << "options: ";
	for (Args::Opt* opt = a.firstopt; opt != 0; opt = opt->next) {
		os << "<" << opt->flag << opt->option << ", " << opt->value_ << "> ";
	}
	os << "\narguments: ";
	for (Args::Arg* arg = a.firstarg; arg != 0; arg = arg->next) {
		os << arg->p << " ";
	}
	return os;
}
#endif

Args::Args(const Args &curr) : optstr(curr.optstr), progname_(curr.progname_), 
firstopt(0), lastopt(0), firstarg(0), lastarg(0)
{
	opterr = curr.opterr;
	plus = curr.plus;
	nargs_ = curr.nargs_;

	for (Opt* opt = curr.firstopt; opt != 0; ) {
		Opt *tempopt = new Opt (*opt);
		
        	tempopt->prev = lastopt;
        	if (lastopt == 0) {
                	firstopt = tempopt;
        	}
        	else {
                	lastopt->next = tempopt;
        	}
        	lastopt = tempopt;
		opt = opt->next;
        }
	for (Arg* arg = curr.firstarg; arg != 0; ) {
		Arg *temparg = new Arg (*arg);
		
        	if (lastarg == 0) {
                	firstarg = temparg;
        	}
        	else {
                	lastarg->next = temparg;
        	}
        	lastarg = temparg;
		arg = arg->next;
        }
}
 
Opt::Opt(const Opt &curr) : key(curr.key), value_(curr.value_), next(0), prev(0), buf(0), firstsubopt(0),
lastsubopt(0)
{ 
	flag_ = curr.flag_;
	chr_ = curr.chr_;
	if (curr.buf) {
		buf = new char[strlen(curr.buf)+1];
		strcpy(buf, curr.buf);
	}

	for (Subopt* subopt = curr.firstsubopt; subopt != 0; ) {
		Subopt *tempsubopt = new Subopt (*subopt);
        	tempsubopt->prev = lastsubopt;
        	if (lastsubopt == 0) {
                	firstsubopt = tempsubopt;
        	}
        	else {
                	lastsubopt->next = tempsubopt;
        	}
        	lastsubopt = tempsubopt;
		subopt = subopt->next;
	}
}


« April 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: