/*
 * $RCSfile: romopt.c,v $
 *
 * x-kernel v3.3
 *
 * Copyright (c) 1993,1991,1990,1996  Arizona Board of Regents
 *
 * $Log: romopt.c,v $
 * Revision 1.2  1996/01/29 19:56:14  slm
 * Updated copyright and version.
 *
 * Revision 1.1  1995/07/28  21:41:44  slm
 * Initial revision
 *
 * Revision 1.8.2.1  1994/10/27  20:52:13  hkaram
 * New branch
 *
 * Revision 1.8  1994/02/04  23:37:17  menze
 *   [ 1994/01/13          menze ]
 *   Need to include rom.h to get rom declarations
 */

/*
 * Library support for processing romfile options
 */

#include "xkernel.h"
#include "romopt.h"
#include "rom.h"

typedef struct {
    char  *name;
    int   minFields;
    XkReturn (* func)();
} GenericRomOpt;

#ifdef __STDC__
static XkReturn findOptions(char *, char *, GenericRomOpt *, int, void *,
			    Protl);
#endif /* __STDC__ */

static XkReturn
findOptions(name, fullName, opts, numOpts, arg, protocol)
char          *name, *fullName;
GenericRomOpt *opts;
int           numOpts;
VOID          *arg;
Protl         protocol;
{
    int           line, j, nFields;
    XkReturn      xkr;
    GenericRomOpt *opt = 0;

    for (line = 0; rom[line][0]; line++) {
	if (!strcmp(rom[line][0], name) || !strcmp(rom[line][0], fullName)) {
	    for (j = 0; j < numOpts; j++) {
		opt = &opts[j];
		if (strlen(opt->name) == 0) {
		    /*
		     * a default option -- issue warning if it's not
		     * the last option
		     */
		    if (j+1 != numOpts) {
			sprintf(errBuf,
	    "xkernel findRomOpts WARNING: %s options after default are ignored",
				fullName);
			xError(errBuf);
		    }
		    break;
		}
		if (rom[line][1] && !strcmp(opt->name, rom[line][1])) {
		    break;
		}
	    }
	    if (j < numOpts) {
		xAssert(opt);
		for (nFields = 1; rom[line][nFields] != 0; nFields++)
		  ;
		if (nFields < opt->minFields) {
		    sprintf(errBuf,
		            "romfile error(%s): not enough fields on line %d",
			    fullName, line+1);
		    xError(errBuf);
		    return XK_FAILURE;
		}
		if (protocol)
		    xkr = opt->func(protocol, rom[line], nFields, line+1, arg);
		else
		    xkr = opt->func(rom[line], nFields, line+1, arg);
		if (xkr == XK_FAILURE) {
		    sprintf(errBuf, "romfile error(%s): bad format on line %d",
			    fullName, line+1);
		    xError(errBuf);
		    return XK_FAILURE;
		}
	    } else {
		sprintf(errBuf,
		        "romfile error(%s): unhandled option \"%s\" on line %d",
			fullName, rom[line][1], line+1);
		    xError(errBuf);
		    return XK_FAILURE;
	    }
	}
    }
    return XK_SUCCESS;
}

XkReturn
findProtlRomOpts(protocol, opt, numOpts, arg)
Protl       protocol;
ProtlRomOpt *opt;
int         numOpts;
VOID        *arg;
{
    return findOptions(protocol->name, protocol->fullName, (GenericRomOpt *)opt,
		       numOpts, arg, protocol);
}

XkReturn
findRomOpts(str, opt, numOpts, arg)
char   *str;
RomOpt *opt;
int    numOpts;
VOID   *arg;
{
    return findOptions(str, str, (GenericRomOpt *)opt, numOpts, arg, 0);
}
