151 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			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 $
 | |
|  */
 | 
