142 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			142 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include "sysutil.h"
 | |
| #include <stdlib.h>
 | |
| #include <env.h>
 | |
| #include <string.h>
 | |
| 
 | |
| 
 | |
| /*=========================================================================*
 | |
|  *				env_parse				   *
 | |
|  *=========================================================================*/
 | |
| PUBLIC int env_parse(env, fmt, field, param, min, max)
 | |
| char *env;		/* environment variable to inspect */
 | |
| char *fmt;		/* template to parse it with */
 | |
| int field;		/* field number of value to return */
 | |
| long *param;		/* address of parameter to get */
 | |
| long min, max;		/* minimum and maximum values for the parameter */
 | |
| {
 | |
| /* Parse an environment variable setting, something like "DPETH0=300:3".
 | |
|  * Panic if the parsing fails.  Return EP_UNSET if the environment variable
 | |
|  * is not set, EP_OFF if it is set to "off", EP_ON if set to "on" or a
 | |
|  * field is left blank, or EP_SET if a field is given (return value through
 | |
|  * *param).  Punctuation may be used in the environment and format string,
 | |
|  * fields in the environment string may be empty, and punctuation may be
 | |
|  * missing to skip fields.  The format string contains characters 'd', 'o',
 | |
|  * 'x' and 'c' to indicate that 10, 8, 16, or 0 is used as the last argument
 | |
|  * to strtol().  A '*' means that a field should be skipped.  If the format
 | |
|  * string contains something like "\4" then the string is repeated 4 characters
 | |
|  * to the left.
 | |
|  */
 | |
|   char *val, *end;
 | |
|   char value[EP_BUF_SIZE];
 | |
|   char PUNCT[] = ":,;.";
 | |
|   long newpar;
 | |
|   int s, i, radix, r;
 | |
| 
 | |
|   if ((s=env_get_param(env, value, sizeof(value))) != 0) { 
 | |
|       if (s == ESRCH) return(EP_UNSET);		/* only error allowed */ 
 | |
|       printf("WARNING: env_get_param() failed in env_parse(): %d\n",s);
 | |
|       return(EP_EGETKENV);
 | |
|   }
 | |
|   val = value;
 | |
|   if (strcmp(val, "off") == 0) return(EP_OFF);
 | |
|   if (strcmp(val, "on") == 0) return(EP_ON);
 | |
| 
 | |
|   i = 0;
 | |
|   r = EP_ON;
 | |
|   for (;;) {
 | |
| 	while (*val == ' ') val++;	/* skip spaces */
 | |
| 	if (*val == 0) return(r);	/* the proper exit point */
 | |
| 	if (*fmt == 0) break;		/* too many values */
 | |
| 
 | |
| 	if (strchr(PUNCT, *val) != NULL) {
 | |
| 		/* Time to go to the next field. */
 | |
| 		if (strchr(PUNCT, *fmt) != NULL) i++;
 | |
| 		if (*fmt++ == *val) val++;
 | |
| 		if (*fmt < 32) fmt -= *fmt;	/* step back? */
 | |
| 	} else {
 | |
| 		/* Environment contains a value, get it. */
 | |
| 		switch (*fmt) {
 | |
| 		case '*':	radix =   -1;	break;
 | |
| 		case 'd':	radix =   10;	break;
 | |
| 		case 'o':	radix =  010;	break;
 | |
| 		case 'x':	radix = 0x10;	break;
 | |
| 		case 'c':	radix =    0;	break;
 | |
| 		default:	goto badenv;
 | |
| 		}
 | |
| 		
 | |
| 		if (radix < 0) {
 | |
| 			/* Skip. */
 | |
| 			while (strchr(PUNCT, *val) == NULL) val++;
 | |
| 			continue;
 | |
| 		} else {
 | |
| 			/* A number. */
 | |
| 			newpar = strtol(val, &end, radix);
 | |
| 
 | |
| 			if (end == val) break;	/* not a number */
 | |
| 			val = end;
 | |
| 		}
 | |
| 
 | |
| 		if (i == field) {
 | |
| 			/* The field requested. */
 | |
| 			if (newpar < min || newpar > max) break;
 | |
| 			*param = newpar;
 | |
| 			r = EP_SET;
 | |
| 		}
 | |
| 	}
 | |
|   }
 | |
| badenv:
 | |
|   env_panic(env);
 | |
|   return -1;
 | |
| }
 | |
| 
 | |
| /*=========================================================================*
 | |
|  *				env_memory_parse			   *
 | |
|  *=========================================================================*/
 | |
| 
 | |
| PUBLIC int env_memory_parse(mem_chunks, maxchunks)
 | |
| struct memory *mem_chunks;	/* where to store the memory bits */
 | |
| int maxchunks;			/* how many were found */
 | |
| {
 | |
|   int i, done = 0;
 | |
|   char *s;
 | |
|   struct memory *memp;
 | |
|   char memstr[100], *end;
 | |
| 
 | |
|   /* Initialize everything to zero. */
 | |
|   for (i = 0; i < maxchunks; i++) {
 | |
| 	memp = &mem_chunks[i];		/* next mem chunk is stored here */
 | |
| 	memp->base = memp->size = 0;
 | |
|   }
 | |
| 
 | |
|   /* The available memory is determined by MINIX' boot loader as a list of 
 | |
|    * (base:size)-pairs in boothead.s. The 'memory' boot variable is set in
 | |
|    * in boot.s.  The format is "b0:s0,b1:s1,b2:s2", where b0:s0 is low mem,
 | |
|    * b1:s1 is mem between 1M and 16M, b2:s2 is mem above 16M. Pairs b1:s1 
 | |
|    * and b2:s2 are combined if the memory is adjacent. 
 | |
|    */
 | |
|   if(env_get_param("memory", memstr, sizeof(memstr)-1) != OK)
 | |
| 	return -1;
 | |
|   s = memstr;
 | |
|   for (i = 0; i < maxchunks && !done; i++) {
 | |
|   	phys_bytes base = 0, size = 0, limit;
 | |
| 	memp = &mem_chunks[i];		/* next mem chunk is stored here */
 | |
| 	if (*s != 0) {			/* get fresh data, unless at end */	
 | |
| 
 | |
| 	    /* Read fresh base and expect colon as next char. */ 
 | |
| 	    base = strtoul(s, &end, 0x10);		/* get number */
 | |
| 	    if (end != s && *end == ':') s = ++end;	/* skip ':' */ 
 | |
| 	    else *s=0;			/* terminate, should not happen */
 | |
| 
 | |
| 	    /* Read fresh size and expect comma or assume end. */ 
 | |
| 	    size = strtoul(s, &end, 0x10);		/* get number */
 | |
| 	    if (end != s && *end == ',') s = ++end;	/* skip ',' */
 | |
| 	    else done = 1;
 | |
| 	}
 | |
| 	if (base + size <= base) continue;
 | |
| 	memp->base = base;
 | |
| 	memp->size = size;
 | |
|   }
 | |
| 
 | |
|   return OK;
 | |
| }
 | 
