/*
 * 5799-WZQ (C) COPYRIGHT = NONE
 * LICENSED MATERIALS - PROPERTY OF IBM
 */
/* $Header:parse.c 12.0$ */
/* $ACIS:parse.c 12.0$ */
/* $Source: /ibm/acis/usr/src/ibm/rvd/lib/RCS/parse.c,v $ */

#ifndef lint
static char *rcsid = "$Header:parse.c 12.0$";
#endif


#ifndef lint
static char rcsid_parse_c[] = "$Header:parse.c 12.0$";
#endif lint

/* Copyright 1984 by the Massachusetts Institute of Technology */
/* See permission and disclaimer notice in the file "notice.h" */
#include "notice.h"


#include <stdio.h>
#include "clnt_ctl.h"

#define	FMT_KEYWRD	"%[^=\r\n \t]"
#define	FMT_VALUE	"%[^\r\n \t]"

#define	HANDLE		"success"

#define	MAXPKT		512

#define	RND(x,y)	((x) - ((x) % (y)))

#ifdef	DEBUG
static char	*z;
#define	psubstr(a,b)	{	for(z = a; z <= b; ++z) \
					putchar(*z); \
				putchar('\n'); \
				fflush(stdout); \
			}
#else	! DEBUG
#define	psubstr(a,b)
#endif	! DEBUG

char	*search();

char	*k[20], *v[20];
char	parse_buf[MAXPKT];

char *
ln_scan(s, kywrd, val, buf)
char	**s, **kywrd, **val, **buf;
{
	char	*p = *s, *k, *v, *m = *buf;

	cpscanf(&p, " ");		/* eatup spaces */

	if(! *p)			/* empty string */
		return(NULL);

	if(cpscanf(&p, FMT_KEYWRD, (k = m)) != 1) {
		puts("ln_scan: missing/illegal keyword");
/**/		psubstr(*s,p);
		return(NULL);
	}

	m += (strlen(k) + 1);		/* count null, too */

	if(*(p++) != '=') {		/* no equals sign */
		puts("ln_scan: missing equals");
/**/		psubstr(*s,p);
		return(NULL);
	}

	if(cpscanf(&p, FMT_VALUE, (v = m)) != 1) {
		puts("ln_scan: missing/illegal value");
/**/		psubstr(*s,p);
		return(NULL);
	}
	else if(*p)
		++p;

	m += (strlen(v) + 1);		/* count null, too */

	cpscanf(&p, " ");		/* eatup spaces */

	*kywrd = k;
	*val = v;
	*buf = m;
	return(*s = p);
}

pkt_scan(s)

char	*s;
{
	char	*m;
	int	i;

	m = parse_buf;

	for(i = 0; ln_scan(&s, &k[i], &v[i], &m); ++i)
		;

	if(! i)
		puts("pkt_scan: garbled packet!");

	return(i);
}

pkt_parse(s)

char	*s;
{
	int	mask = 0, allowed, nflds, i ;
	op	*o;
	tag	*t;

	if((nflds = pkt_scan(s)) == 0)
		return(NULL);

	if(! strcmp(k[0], "success")) {
		if((o = (op *) search(v[0], &op_tbl[1], &op_tbl[NOP - 1],
		  sizeof(op))) == NULL) {
			printf("pkt_parse: unknown operation, `%s'\n", v[0]);
			return(NULL);
		}
	}
	else {
		if(! strcmp(k[0], "failure"))
			o = &op_tbl[0];
		else {
			printf("pkt_parse: expected `%s' keyword, found `%s'\n",
			  "success", k[0]);
			return(NULL);
		}
	}

	allowed = o->optnl | o->reqrd;
	V(_KEYWORD) = v[0];

	for(i = 0; i < NTAG; ++i)
		tag_tbl[i].fnd = 0;

	for(i = 1; i < nflds; ++i) {
		if((t = (tag *) search(k[i], &tag_tbl[0], &tag_tbl[NTAG - 1],
		  sizeof(tag))) == NULL || (t->alias & ~allowed)) {
			printf("pkt_parse: inappropriate tag, `%s'.\n", k[i]);
			continue;
		}
		*(t->val) = v[i];
		t->fnd = 1;
		mask |= t->alias;
	}

	if((mask | ~o->reqrd) != ~0) {
		printf("pkt_parse: required fields missing\n");
		return(NULL);
	}
	return(nflds);
}

char *
search(str, low, high, size)

char	*str, **low, **high;
int	size;

{
	char	**mid;
	int	diff, spc;

	for(; low <= high; mid = NULL) {
		spc = high - low;
		mid = low + RND(spc / 2, size);
		if((diff = strcmp(str, *mid)) == 0)
			break;
		else if(diff < 0)
			high = (char **) ((char *) mid - size);
		else
			low = (char **) ((char *) mid + size);
	}
	return((char *) mid);
}
