minix3/net/inet/queryparam.c

151 lines
3.1 KiB
C

/* queryparam() - allow program parameters to be queried
* Author: Kees J. Bot
* 21 Apr 1994
*/
#define nil 0
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "queryparam.h"
#if EXAMPLE
struct stat st[2];
struct export_param_list ex_st_list[]= {
QP_VARIABLE(st),
QP_ARRAY(st),
QP_FIELD(st_dev, struct stat),
QP_FIELD(st_ino, struct stat),
...
QP_END()
};
struct buf { block_t b_blocknr; ... } *buf;
size_t nr_bufs;
struct export_param_list ex_buf_list[]=
QP_VECTOR(buf, buf, nr_bufs),
QP_FIELD(b_blocknr),
...
QP_END()
};
struct export_params ex_st= { ex_st_list, 0 };
struct export_params ex_buf= { ex_buf_list, 0 };
#endif
#define between(a, c, z) ((unsigned) ((c) - (a)) <= (unsigned) ((z) - (a)))
static int isvar(int c)
{
return between('a', c, 'z') || between('A', c, 'Z')
|| between('0', c, '9') || c == '_';
}
static struct export_params *params;
void qp_export(struct export_params *ex_params)
{
/* Add a set of exported parameters. */
if (ex_params->next == nil) {
ex_params->next= params;
params= ex_params;
}
}
int queryparam(int qgetc(void), void **poffset, size_t *psize)
{
char *prefix;
struct export_params *ep;
struct export_param_list *epl;
size_t offset= 0;
size_t size= -1;
size_t n;
static size_t retval;
int c, firstc;
firstc= c= (*qgetc)();
if (c == '&' || c == '$') c= (*qgetc)();
if (!isvar(c)) goto fail;
if ((ep= params) == nil) goto fail;
epl= ep->list;
while (c != 0 && c != ',') {
prefix= (char *) "x";
n= 0;
for (;;) {
while (epl->name == nil) {
if ((ep= ep->next) == nil) goto fail;
epl= ep->list;
}
if (strncmp(prefix, epl->name, n) == 0) {
prefix= epl->name;
while (prefix[n] != 0 && c == prefix[n]) {
n++;
c= (*qgetc)();
}
}
if (prefix[n] == 0 && (!isvar(c) || prefix[0] == '[')) {
/* Got a match. */
break;
}
epl++;
}
if (prefix[0] == '[') {
/* Array reference. */
size_t idx= 0, cnt= 1, max= size / epl->size;
while (between('0', c, '9')) {
idx= idx * 10 + (c - '0');
if (idx > max) goto fail;
c= (*qgetc)();
}
if (c == ':') {
cnt= 0;
while (between('0', (c= (*qgetc)()), '9')) {
cnt= cnt * 10 + (c - '0');
}
}
if (c != ']') goto fail;
if (idx + cnt > max) cnt= max - idx;
offset+= idx * epl->size;
size= cnt * epl->size;
c= (*qgetc)();
} else
if (epl->size == -1) {
/* Vector. */
offset= (size_t) * (void **) epl->offset;
size= (* (size_t *) epl[1].offset) * epl[1].size;
} else {
/* Variable or struct field. */
offset+= (size_t) epl->offset;
if ((size_t) epl->offset > size) goto fail;
size-= (size_t) epl->offset;
if (size < epl->size) goto fail;
size= epl->size;
}
}
if (firstc == '&' || firstc == '$') {
retval= firstc == '&' ? offset : size;
offset= (size_t) &retval;
size= sizeof(retval);
}
if (c != 0 && c != ',') goto fail;
*poffset= (void *) offset;
*psize= size;
return c != 0;
fail:
while (c != 0 && c != ',') c= (*qgetc)();
*poffset= nil;
*psize= 0;
return c != 0;
}
/*
* $PchId: queryparam.c,v 1.1 2005/06/28 14:30:56 philip Exp $
*/