⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 parse.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 5 页
字号:
	const char *ptr = str;	int negative = 0;	u_int32_t val = 0;	int tval;	int max;	if (*ptr == '-') {		negative = 1;		++ptr;	}	/* If base wasn't specified, figure it out from the data. */	if (!base) {		if (ptr [0] == '0') {			if (ptr [1] == 'x') {				base = 16;				ptr += 2;			} else if (isascii (ptr [1]) && isdigit (ptr [1])) {				base = 8;				ptr += 1;			} else {				base = 10;			}		} else {			base = 10;		}	}	do {		tval = *ptr++;		/* XXX assumes ASCII... */		if (tval >= 'a')			tval = tval - 'a' + 10;		else if (tval >= 'A')			tval = tval - 'A' + 10;		else if (tval >= '0')			tval -= '0';		else {			parse_warn (cfile, "Bogus number: %s.", str);			break;		}		if (tval >= base) {			parse_warn (cfile,				    "Bogus number %s: digit %d not in base %d",				    str, tval, base);			break;		}		val = val * base + tval;	} while (*ptr);	if (negative)		max = (1 << (size - 1));	else		max = (1 << (size - 1)) + ((1 << (size - 1)) - 1);	if (val > max) {		switch (base) {		      case 8:			parse_warn (cfile,				    "%s%lo exceeds max (%d) for precision.",				    negative ? "-" : "",				    (unsigned long)val, max);			break;		      case 16:			parse_warn (cfile,				    "%s%lx exceeds max (%d) for precision.",				    negative ? "-" : "",				    (unsigned long)val, max);			break;		      default:			parse_warn (cfile,				    "%s%lu exceeds max (%d) for precision.",				    negative ? "-" : "",				    (unsigned long)val, max);			break;		}	}	if (negative) {		switch (size) {		      case 8:			*buf = -(unsigned long)val;			break;		      case 16:			putShort (buf, -(long)val);			break;		      case 32:			putLong (buf, -(long)val);			break;		      default:			parse_warn (cfile,				    "Unexpected integer size: %d\n", size);			break;		}	} else {		switch (size) {		      case 8:			*buf = (u_int8_t)val;			break;		      case 16:			putUShort (buf, (u_int16_t)val);			break;		      case 32:			putULong (buf, val);			break;		      default:			parse_warn (cfile,				    "Unexpected integer size: %d\n", size);			break;		}	}}/* * date :== NUMBER NUMBER SLASH NUMBER SLASH NUMBER  *		NUMBER COLON NUMBER COLON NUMBER SEMI | *          NUMBER NUMBER SLASH NUMBER SLASH NUMBER  *		NUMBER COLON NUMBER COLON NUMBER NUMBER SEMI | *	    NEVER * * Dates are stored in GMT or with a timezone offset; first number is day * of week; next is year/month/day; next is hours:minutes:seconds on a * 24-hour clock, followed by the timezone offset in seconds, which is * optional. */TIME parse_date (cfile)	struct parse *cfile;{	struct tm tm;	int guess;	int tzoff, wday, year, mon, mday, hour, min, sec;	const char *val;	enum dhcp_token token;	static int months [11] = { 31, 59, 90, 120, 151, 181,					  212, 243, 273, 304, 334 };	/* Day of week, or "never"... */	token = next_token (&val, (unsigned *)0, cfile);	if (token == NEVER) {		if (!parse_semi (cfile))			return 0;		return MAX_TIME;	}	if (token != NUMBER) {		parse_warn (cfile, "numeric day of week expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	wday = atoi (val);	/* Year... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "numeric year expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	/* Note: the following is not a Y2K bug - it's a Y1.9K bug.   Until	   somebody invents a time machine, I think we can safely disregard	   it.   This actually works around a stupid Y2K bug that was present	   in a very early beta release of dhcpd. */	year = atoi (val);	if (year > 1900)		year -= 1900;	/* Slash seperating year from month... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != SLASH) {		parse_warn (cfile,			    "expected slash seperating year from month.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	/* Month... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "numeric month expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	mon = atoi (val) - 1;	/* Slash seperating month from day... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != SLASH) {		parse_warn (cfile,			    "expected slash seperating month from day.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	/* Month... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "numeric day of month expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	mday = atoi (val);	/* Hour... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "numeric hour expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	hour = atoi (val);	/* Colon seperating hour from minute... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != COLON) {		parse_warn (cfile,			    "expected colon seperating hour from minute.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	/* Minute... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "numeric minute expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	min = atoi (val);	/* Colon seperating minute from second... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != COLON) {		parse_warn (cfile,			    "expected colon seperating hour from minute.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	/* Minute... */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "numeric minute expected.");		if (token != SEMI)			skip_to_semi (cfile);		return (TIME)0;	}	sec = atoi (val);	token = peek_token (&val, (unsigned *)0, cfile);	if (token == NUMBER) {		token = next_token (&val, (unsigned *)0, cfile);		tzoff = atoi (val);	} else		tzoff = 0;	/* Make sure the date ends in a semicolon... */	if (!parse_semi (cfile))		return 0;	/* Guess the time value... */	guess = ((((((365 * (year - 70) +	/* Days in years since '70 */		      (year - 69) / 4 +		/* Leap days since '70 */		      (mon			/* Days in months this year */		       ? months [mon - 1]		       : 0) +		      (mon > 1 &&		/* Leap day this year */		       !((year - 72) & 3)) +		      mday - 1) * 24) +		/* Day of month */		    hour) * 60) +		  min) * 60) + sec + tzoff;	/* This guess could be wrong because of leap seconds or other	   weirdness we don't know about that the system does.   For	   now, we're just going to accept the guess, but at some point	   it might be nice to do a successive approximation here to	   get an exact value.   Even if the error is small, if the	   server is restarted frequently (and thus the lease database	   is reread), the error could accumulate into something	   significant. */	return guess;}/* * option-name :== IDENTIFIER | 		   IDENTIFIER . IDENTIFIER */struct option *parse_option_name (cfile, allocate, known)	struct parse *cfile;	int allocate;	int *known;{	const char *val;	enum dhcp_token token;	char *uname;	struct universe *universe;	struct option *option;	token = next_token (&val, (unsigned *)0, cfile);	if (!is_identifier (token)) {		parse_warn (cfile,			    "expecting identifier after option keyword.");		if (token != SEMI)			skip_to_semi (cfile);		return (struct option *)0;	}	uname = dmalloc (strlen (val) + 1, MDL);	if (!uname)		log_fatal ("no memory for uname information.");	strcpy (uname, val);	token = peek_token (&val, (unsigned *)0, cfile);	if (token == DOT) {		/* Go ahead and take the DOT token... */		token = next_token (&val, (unsigned *)0, cfile);		/* The next token should be an identifier... */		token = next_token (&val, (unsigned *)0, cfile);		if (!is_identifier (token)) {			parse_warn (cfile, "expecting identifier after '.'");			if (token != SEMI)				skip_to_semi (cfile);			return (struct option *)0;		}		/* Look up the option name hash table for the specified		   uname. */		universe = (struct universe *)0;		if (!universe_hash_lookup (&universe, universe_hash,					   uname, 0, MDL)) {			parse_warn (cfile, "no option space named %s.", uname);			skip_to_semi (cfile);			return (struct option *)0;		}	} else {		/* Use the default hash table, which contains all the		   standard dhcp option names. */		val = uname;		universe = &dhcp_universe;	}	/* Look up the actual option info... */	option = (struct option *)0;	option_hash_lookup (&option, universe -> hash, val, 0, MDL);	/* If we didn't get an option structure, it's an undefined option. */	if (option) {		if (known)			*known = 1;	} else {		/* If we've been told to allocate, that means that this		   (might) be an option code definition, so we'll create		   an option structure just in case. */		if (allocate) {			option = new_option (MDL);			if (val == uname)				option -> name = val;			else {				char *s;				dfree (uname, MDL);				s = dmalloc (strlen (val) + 1, MDL);				if (!s)				    log_fatal ("no memory for option %s.%s",					       universe -> name, val);				strcpy (s, val);				option -> name = s;			}			option -> universe = universe;			option -> code = 0;			return option;		}		if (val == uname)			parse_warn (cfile, "no option named %s", val);		else			parse_warn (cfile, "no option named %s in space %s",				    val, uname);		skip_to_semi (cfile);		return (struct option *)0;	}	/* Free the initial identifier token. */	dfree (uname, MDL);	return option;}/* IDENTIFIER SEMI */void parse_option_space_decl (cfile)	struct parse *cfile;{	int token;	const char *val;	struct universe **ua, *nu;	char *s;	next_token (&val, (unsigned *)0, cfile);  /* Discard the SPACE token,						     which was checked by the						     caller. */	token = next_token (&val, (unsigned *)0, cfile);	if (!is_identifier (token)) {		parse_warn (cfile, "expecting identifier.");		skip_to_semi (cfile);		return;	}	nu = new_universe (MDL);	if (!nu)		log_fatal ("No memory for new option space.");	/* Set up the server option universe... */	s = dmalloc (strlen (val) + 1, MDL);	if (!s)		log_fatal ("No memory for new option space name.");	strcpy (s, val);	nu -> name = s;	nu -> lookup_func = lookup_hashed_option;	nu -> option_state_dereference =		hashed_option_state_dereference;	nu -> foreach = hashed_option_space_foreach;	nu -> save_func = save_hashed_option;	nu -> delete_func = delete_hashed_option;	nu -> encapsulate = hashed_option_space_encapsulate;	nu -> decode = parse_option_buffer;	nu -> length_size = 1;	nu -> tag_size = 1;	nu -> store_tag = putUChar;	nu -> store_length = putUChar;	nu -> index = universe_count++;	if (nu -> index >= universe_max) {		ua = dmalloc (universe_max * 2 * sizeof *ua, MDL);		if (!ua)			log_fatal ("No memory to expand option space array.");		memcpy (ua, universes, universe_max * sizeof *ua);		universe_max *= 2;		dfree (universes, MDL);		universes = ua;	}	universes [nu -> index] = nu;	option_new_hash (&nu -> hash, 1, MDL);	if (!nu -> hash)		log_fatal ("Can't allocate %s option hash table.", nu -> name);	universe_hash_add (universe_hash, nu -> name, 0, nu, MDL);	parse_semi (cfile);}/* This is faked up to look good right now.   Ideally, this should do a   recursive parse and allow arbitrary data structure definitions, but for   now it just allows you to specify a single type, an array of single types,   a sequence of types, or an array of sequences of types.   ocd :== NUMBER EQUALS ocsd SEMI   ocsd :== ocsd_type |	    ocsd_type_sequence |	    ARRAY OF ocsd_simple_type_sequence   ocsd_type_sequence :== LBRACE ocsd_types RBRACE   ocsd_simple_type_sequence :== LBRACE ocsd_simple_types RBRACE   ocsd_types :== ocsd_type |		  ocsd_types ocsd_type   ocsd_type :== ocsd_simple_type |		 ARRAY OF ocsd_simple_type   ocsd_simple_types :== ocsd_simple_type |			 ocsd_simple_types ocsd_simple_type   ocsd_simple_type :== BOOLEAN |			INTEGER NUMBER |			SIGNED INTEGER NUMBER |			UNSIGNED INTEGER NUMBER |			IP-ADDRESS |			TEXT |			STRING |			ENCAPSULATE identifier */int parse_option_code_definition (cfile, option)	struct parse *cfile;	struct option *option;{	const char *val;	enum dhcp_token token;	unsigned arrayp = 0;	int recordp = 0;	int no_more_in_record = 0;	char tokbuf [128];	unsigned tokix = 0;	char type;	int code;	int is_signed;	char *s;	int has_encapsulation = 0;		/* Parse the option code. */	token = next_token (&val, (unsigned *)0, cfile);	if (token != NUMBER) {		parse_warn (cfile, "expecting option code number.");		skip_to_semi (cfile);		return 0;	}	option -> code = atoi (val);	token = next_token (&val, (unsigned *)0, cfile);	if (token != EQUAL) {		parse_warn (cfile, "expecting \"=\"");		skip_to_semi (cfile);		return 0;	}	/* See if this is an array. */	token = next_token (&val, (unsigned *)0, cfile);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -