q->str_value = calloc(1, sizeof(char *));
q->str_value = typecalloc(char *);
PRIVATE void do_read_cfg ARGS5(	char *, cfg_filename,	char *, parent_filename,	int,	nesting_level,	FILE *,	fp0,	optidx_set_t*, allowed){    FILE *fp;    char mypath[LY_MAXPATH];    char *buffer = 0;    CTRACE(tfp, "Loading cfg file '%s'.\n", cfg_filename);    /*     *	Don't get hung up by an include file loop.  Arbitrary max depth     *	of 10.	- BL     */    if (nesting_level > 10) {	fprintf(stderr,		gettext("More than %d nested lynx.cfg includes -- perhaps there is a loop?!?\n"),		nesting_level - 1);	fprintf(stderr,gettext("Last attempted include was '%s',\n"), cfg_filename);	fprintf(stderr,gettext("included from '%s'.\n"), parent_filename);	exit(-1);    }    /*     *	Locate and open the file.     */    if (!cfg_filename || strlen(cfg_filename) == 0) {	CTRACE(tfp,"No filename following -cfg switch!\n");	return;    }    if (!strncmp(cfg_filename, "~/", 2)) {	strcpy(mypath, Home_Dir());	strcat(mypath, cfg_filename+1);	cfg_filename = mypath;    }    if ((fp = fopen(cfg_filename,"r")) == 0) {	CTRACE(tfp,"lynx.cfg file not found as %s\n",cfg_filename);	return;    }    have_read_cfg = TRUE;    /*     *	Process each line in the file.     */    while (LYSafeGets(&buffer, fp) != 0) {	char *name, *value;	char *cp;	Config_Type *tbl;#ifdef PARSE_DEBUG	Config_Type *q;#else	ConfigUnion *q;#endif	/* Most lines in the config file are comment lines.  Weed them out	 * now.  Also, leading whitespace is ok, so trim it.	 */	name = LYSkipBlanks(buffer);	if (*name == '#')	    continue;	LYTrimTrailing(name);	if (*name == 0) continue;	/* Significant lines are of the form KEYWORD:WHATEVER */	if ((value = strchr (name, ':')) == 0) {	    /* fprintf (stderr, "Bad line-- no :\n"); */	    continue;	}	/* skip past colon, but replace ':' with 0 to make name meaningful */	*value++ = 0;	/*	 *  Trim off any trailing comments.	 *	 *  (Apparently, the original code considers a trailing comment	 *   valid only if preceded by a space character but is not followed	 *   by a colon.  -- JED)	 */	if ((cp = strrchr (value, ':')) == 0)	    cp = value;	if ((cp = strchr (cp, '#')) != 0) {	    cp--;	    if (isspace ((unsigned char) *cp))		*cp = 0;	}	tbl = lookup_config(name);	if (tbl->name == 0) {	    /* lynx ignores unknown keywords */	    continue;	}	if ( allowed && (*allowed)[ tbl-Config_Table ] ) {	    if (fp0 == NULL)		fprintf (stderr, "%s is not allowed in the %s\n",		    name,cfg_filename);	    /*FIXME: we can do something wiser if we are generating	    the html representation of lynx.cfg - say include this line	    in bold, or something...*/	    continue;	}#ifdef PARSE_DEBUG	q = tbl;#else	q = (ConfigUnion *)(&(tbl->value));#endif	switch ((fp0 != 0 && tbl->type != CONF_INCLUDE)		? CONF_UNSPECIFIED		: tbl->type) {	case CONF_BOOL:	    if (q->set_value != 0)		*(q->set_value) = is_true (value);	    break;	case CONF_FUN:	    if (q->fun_value != 0)		(*(q->fun_value)) (value);	    break;	case CONF_INT:	    if (q->int_value != 0) {		int ival;		/* Apparently, if an integer value is not present, then the		 * value is not changed.  So, use the sscanf function to make		 * this determination.		 */		if (1 == sscanf (value, "%d", &ival))		    *(q->int_value) = ival;	    }	    break;	case CONF_STR:	    if (q->str_value != 0)		StrAllocCopy(*(q->str_value), value);	    break;	case CONF_ENV:	case CONF_ENV2:	    if (tbl->type == CONF_ENV)		LYLowerCase(name);	    else		LYUpperCase(name);	    if (getenv (name) == 0) {#ifdef VMS		Define_VMSLogical(name, value);#else		if (q->str_value == 0)			q->str_value = calloc(1, sizeof(char *));		HTSprintf0 (q->str_value, "%s=%s", name, value);		putenv (*(q->str_value));#endif	    }	    break;	case CONF_INCLUDE: {	    /* include another file */	    optidx_set_t cur_set,anded_set;	    optidx_set_t* resultant_set = NULL;	    char* p1, *p2, savechar;	    BOOL any_optname_found = FALSE;	    char *url = NULL;	    char *cp1 = NULL;	    char *sep = NULL;	    if ( (p1 = strstr(value, sep=" for ")) != 0#if defined(UNIX) && !defined(__EMX__)		|| (p1 = strstr(value, sep=":")) != 0#endif	    ) {		*p1 = '\0';		p1 += strlen(sep);	    }#ifndef NO_CONFIG_INFO	    if (fp0 != 0  &&  !LYRestricted) {		LYLocalFileToURL(&url, value);		StrAllocCopy(cp1, value);		if (strchr(value, '&') || strchr(value, '<')) {		    LYEntify(&cp1, TRUE);		}		fprintf(fp0, "%s:<a href=\"%s\">%s</a>\n\n", name, url, cp1);		fprintf(fp0, "    #&lt;begin  %s&gt;\n", cp1);	    }#endif	    if (p1) {		while (*(p1 = LYSkipBlanks(p1)) != 0) {		    Config_Type *tbl2;		    p2 = LYSkipNonBlanks(p1);		    savechar = *p2;		    *p2 = 0;		    tbl2 = lookup_config(p1);		    if (tbl2->name == 0) {			if (fp0 == NULL)			    fprintf (stderr, "unknown option name %s in %s\n",				     p1, cfg_filename);		    } else {			unsigned i;			if (!any_optname_found) {			    any_optname_found = TRUE;			    for (i = 0; i < NOPTS_; ++i)				cur_set[i] = TRUE;			}			cur_set[tbl2 - Config_Table] = FALSE;		    }		    if (savechar && p2[1])			p1 = p2 + 1;		    else			break;		}	    }	    if (!allowed) {		if (!any_optname_found)		    resultant_set = NULL;		else		    resultant_set = &cur_set;	    } else {		if (!any_optname_found)		    resultant_set = allowed;		else {		    optidx_set_AND(anded_set, *allowed, cur_set);		    resultant_set = &anded_set;		}	    }#ifndef NO_CONFIG_INFO	    /* 	     * Now list the opts that are allowed in included file.  If all	     * opts are allowed, then emit nothing, else emit an effective set	     * of allowed options in <ul>.  Option names will be uppercased. 	     * FIXME:  uppercasing option names can be considered redundant.	     */	    if (fp0 != 0  &&  !LYRestricted && resultant_set) {		char *buf = NULL;		unsigned i;		fprintf(fp0,"     Options allowed in this file:\n");		for (i = 0; i < NOPTS_; ++i) {		    if ((*resultant_set)[i])			continue;		    StrAllocCopy(buf, Config_Table[i].name);		    LYUpperCase(buf);		    fprintf(fp0,"         * %s\n", buf);		}		FREE(buf);	    }#endif	    do_read_cfg (value, cfg_filename, nesting_level + 1, fp0,resultant_set);#ifndef NO_CONFIG_INFO	    if (fp0 != 0  &&  !LYRestricted) {		fprintf(fp0, "    #&lt;end of %s&gt;\n\n", cp1);		FREE(url);		FREE(cp1);	    }#endif	    }	    break;	case CONF_ADD_ITEM:	    if (q->add_value != 0)		add_item_to_list (value, q->add_value);	    break;#if defined(EXEC_LINKS) || defined(LYNXCGI_LINKS)	case CONF_ADD_TRUSTED:	    add_trusted (value, q->def_value);	    break;#endif	default:	    if (fp0 != 0) {		if (strchr(value, '&') || strchr(value, '<')) {		    char *cp1 = NULL;		    StrAllocCopy(cp1, value);		    LYEntify(&cp1, TRUE);		    fprintf(fp0, "%s:%s\n", name, cp1);		    FREE(cp1);		} else {		    fprintf(fp0, "%s:%s\n", name, value);		}	    }	    break;	}    }    fclose (fp);    /*     *	If any DOWNLOADER: commands have always_enabled set (:TRUE),     *	make override_no_download TRUE, so that other restriction     *	settings will not block presentation of a download menu     *	with those always_enabled options still available. - FM     */    if (downloaders != 0) {	lynx_html_item_type *cur_download;	cur_download = downloaders;	while (cur_download != 0) {	    if (cur_download->always_enabled) {		override_no_download = TRUE;		break;	    }	    cur_download = cur_download->next;	}    }    /*     * If any COOKIE_{ACCEPT,REJECT}_DOMAINS have been defined,     * process them.  These are comma delimited lists of     * domains. - BJP     *     * And for query/strict/loose invalid cookie checking. - BJP     */    if (LYCookieSAcceptDomains != NULL) {	cookie_domain_flag_set(LYCookieSAcceptDomains, FLAG_ACCEPT_ALWAYS);	FREE(LYCookieSAcceptDomains);    }    if (LYCookieSRejectDomains != NULL) {	cookie_domain_flag_set(LYCookieSRejectDomains, FLAG_REJECT_ALWAYS);	FREE(LYCookieSRejectDomains);    }    if (LYCookieSStrictCheckDomains != NULL) {	cookie_domain_flag_set(LYCookieSStrictCheckDomains, FLAG_INVCHECK_STRICT);	FREE(LYCookieSStrictCheckDomains);    }    if (LYCookieSLooseCheckDomains != NULL) {	cookie_domain_flag_set(LYCookieSLooseCheckDomains, FLAG_INVCHECK_LOOSE);	FREE(LYCookieSLooseCheckDomains);    }    if (LYCookieSQueryCheckDomains != NULL) {	cookie_domain_flag_set(LYCookieSQueryCheckDomains, FLAG_INVCHECK_QUERY);	FREE(LYCookieSQueryCheckDomains);    }    if (LYCookieAcceptDomains != NULL) {	cookie_domain_flag_set(LYCookieAcceptDomains, FLAG_ACCEPT_ALWAYS);    }    if (LYCookieRejectDomains != NULL) {	cookie_domain_flag_set(LYCookieRejectDomains, FLAG_REJECT_ALWAYS);    }    if (LYCookieStrictCheckDomains != NULL) {	cookie_domain_flag_set(LYCookieStrictCheckDomains, FLAG_INVCHECK_STRICT);    }    if (LYCookieLooseCheckDomains != NULL) {	cookie_domain_flag_set(LYCookieLooseCheckDomains, FLAG_INVCHECK_LOOSE);    }    if (LYCookieQueryCheckDomains != NULL) {	cookie_domain_flag_set(LYCookieQueryCheckDomains, FLAG_INVCHECK_QUERY);    }}