|  | @@ -1007,7 +1007,6 @@ parse_setting_name ( const char *name,
 | 
		
	
		
			
			| 1007 | 1007 |  	char *setting_name;
 | 
		
	
		
			
			| 1008 | 1008 |  	char *type_name;
 | 
		
	
		
			
			| 1009 | 1009 |  	struct setting *named_setting;
 | 
		
	
		
			
			| 1010 |  | -	unsigned int tag;
 | 
		
	
		
			
			| 1011 | 1010 |  
 | 
		
	
		
			
			| 1012 | 1011 |  	/* Set defaults */
 | 
		
	
		
			
			| 1013 | 1012 |  	*settings = &settings_root;
 | 
		
	
	
		
			
			|  | @@ -1038,16 +1037,14 @@ parse_setting_name ( const char *name,
 | 
		
	
		
			
			| 1038 | 1037 |  	}
 | 
		
	
		
			
			| 1039 | 1038 |  
 | 
		
	
		
			
			| 1040 | 1039 |  	/* Identify setting */
 | 
		
	
		
			
			| 1041 |  | -	if ( ( named_setting = find_setting ( setting_name ) ) != NULL ) {
 | 
		
	
		
			
			|  | 1040 | +	setting->tag = parse_setting_tag ( *settings, setting_name );
 | 
		
	
		
			
			|  | 1041 | +	setting->name = setting_name;
 | 
		
	
		
			
			|  | 1042 | +	for_each_table_entry ( named_setting, SETTINGS ) {
 | 
		
	
		
			
			| 1042 | 1043 |  		/* Matches a defined named setting; use that setting */
 | 
		
	
		
			
			| 1043 |  | -		memcpy ( setting, named_setting, sizeof ( *setting ) );
 | 
		
	
		
			
			| 1044 |  | -	} else if ( ( tag = parse_setting_tag ( *settings,
 | 
		
	
		
			
			| 1045 |  | -						setting_name ) ) != 0 ) {
 | 
		
	
		
			
			| 1046 |  | -		/* Is a valid numeric tag; use the tag */
 | 
		
	
		
			
			| 1047 |  | -		setting->tag = tag;
 | 
		
	
		
			
			| 1048 |  | -	} else {
 | 
		
	
		
			
			| 1049 |  | -		/* Use the arbitrary name */
 | 
		
	
		
			
			| 1050 |  | -		setting->name = setting_name;
 | 
		
	
		
			
			|  | 1044 | +		if ( setting_cmp ( named_setting, setting ) == 0 ) {
 | 
		
	
		
			
			|  | 1045 | +			memcpy ( setting, named_setting, sizeof ( *setting ) );
 | 
		
	
		
			
			|  | 1046 | +			break;
 | 
		
	
		
			
			|  | 1047 | +		}
 | 
		
	
		
			
			| 1051 | 1048 |  	}
 | 
		
	
		
			
			| 1052 | 1049 |  
 | 
		
	
		
			
			| 1053 | 1050 |  	/* Identify setting type, if specified */
 | 
		
	
	
		
			
			|  | @@ -1076,30 +1073,57 @@ int storef_named_setting ( const char *name, const char *value ) {
 | 
		
	
		
			
			| 1076 | 1073 |  	char tmp_name[ strlen ( name ) + 1 ];
 | 
		
	
		
			
			| 1077 | 1074 |  	int rc;
 | 
		
	
		
			
			| 1078 | 1075 |  
 | 
		
	
		
			
			|  | 1076 | +	/* Parse setting name */
 | 
		
	
		
			
			| 1079 | 1077 |  	if ( ( rc = parse_setting_name ( name, autovivify_child_settings,
 | 
		
	
		
			
			| 1080 | 1078 |  					 &settings, &setting, tmp_name )) != 0)
 | 
		
	
		
			
			| 1081 | 1079 |  		return rc;
 | 
		
	
		
			
			| 1082 |  | -	return storef_setting ( settings, &setting, value );
 | 
		
	
		
			
			|  | 1080 | +
 | 
		
	
		
			
			|  | 1081 | +	/* Store setting */
 | 
		
	
		
			
			|  | 1082 | +	if ( ( rc = storef_setting ( settings, &setting, value ) ) != 0 )
 | 
		
	
		
			
			|  | 1083 | +		return rc;
 | 
		
	
		
			
			|  | 1084 | +
 | 
		
	
		
			
			|  | 1085 | +	return 0;
 | 
		
	
		
			
			| 1083 | 1086 |  }
 | 
		
	
		
			
			| 1084 | 1087 |  
 | 
		
	
		
			
			| 1085 | 1088 |  /**
 | 
		
	
		
			
			| 1086 | 1089 |   * Fetch and format value of named setting
 | 
		
	
		
			
			| 1087 | 1090 |   *
 | 
		
	
		
			
			| 1088 | 1091 |   * @v name		Name of setting
 | 
		
	
		
			
			| 1089 |  | - * @v buf		Buffer to contain formatted value
 | 
		
	
		
			
			| 1090 |  | - * @v len		Length of buffer
 | 
		
	
		
			
			|  | 1092 | + * @v name_buf		Buffer to contain canonicalised name
 | 
		
	
		
			
			|  | 1093 | + * @v name_len		Length of canonicalised name buffer
 | 
		
	
		
			
			|  | 1094 | + * @v value_buf		Buffer to contain formatted value
 | 
		
	
		
			
			|  | 1095 | + * @v value_len		Length of formatted value buffer
 | 
		
	
		
			
			| 1091 | 1096 |   * @ret len		Length of formatted value, or negative error
 | 
		
	
		
			
			| 1092 | 1097 |   */
 | 
		
	
		
			
			| 1093 |  | -int fetchf_named_setting ( const char *name, char *buf, size_t len ) {
 | 
		
	
		
			
			|  | 1098 | +int fetchf_named_setting ( const char *name,
 | 
		
	
		
			
			|  | 1099 | +			   char *name_buf, size_t name_len,
 | 
		
	
		
			
			|  | 1100 | +			   char *value_buf, size_t value_len ) {
 | 
		
	
		
			
			| 1094 | 1101 |  	struct settings *settings;
 | 
		
	
		
			
			| 1095 | 1102 |  	struct setting setting;
 | 
		
	
		
			
			|  | 1103 | +	struct settings *origin;
 | 
		
	
		
			
			|  | 1104 | +	const char *origin_name;
 | 
		
	
		
			
			| 1096 | 1105 |  	char tmp_name[ strlen ( name ) + 1 ];
 | 
		
	
		
			
			| 1097 | 1106 |  	int rc;
 | 
		
	
		
			
			| 1098 | 1107 |  
 | 
		
	
		
			
			|  | 1108 | +	/* Parse setting name */
 | 
		
	
		
			
			| 1099 | 1109 |  	if ( ( rc = parse_setting_name ( name, find_child_settings,
 | 
		
	
		
			
			| 1100 | 1110 |  					 &settings, &setting, tmp_name )) != 0)
 | 
		
	
		
			
			| 1101 | 1111 |  		return rc;
 | 
		
	
		
			
			| 1102 |  | -	return fetchf_setting ( settings, &setting, buf, len );
 | 
		
	
		
			
			|  | 1112 | +
 | 
		
	
		
			
			|  | 1113 | +	/* Fetch setting */
 | 
		
	
		
			
			|  | 1114 | +	if ( ( rc = fetchf_setting ( settings, &setting, value_buf,
 | 
		
	
		
			
			|  | 1115 | +				     value_len ) ) < 0 )
 | 
		
	
		
			
			|  | 1116 | +		return rc;
 | 
		
	
		
			
			|  | 1117 | +
 | 
		
	
		
			
			|  | 1118 | +	/* Construct setting name */
 | 
		
	
		
			
			|  | 1119 | +	origin = fetch_setting_origin ( settings, &setting );
 | 
		
	
		
			
			|  | 1120 | +	assert ( origin != NULL );
 | 
		
	
		
			
			|  | 1121 | +	origin_name = settings_name ( origin );
 | 
		
	
		
			
			|  | 1122 | +	snprintf ( name_buf, name_len, "%s%s%s:%s",
 | 
		
	
		
			
			|  | 1123 | +		   origin_name, ( origin_name[0] ? "/" : "" ),
 | 
		
	
		
			
			|  | 1124 | +		   setting.name, setting.type->name );
 | 
		
	
		
			
			|  | 1125 | +
 | 
		
	
		
			
			|  | 1126 | +	return 0;
 | 
		
	
		
			
			| 1103 | 1127 |  }
 | 
		
	
		
			
			| 1104 | 1128 |  
 | 
		
	
		
			
			| 1105 | 1129 |  /******************************************************************************
 | 
		
	
	
		
			
			|  | @@ -1597,7 +1621,7 @@ char * expand_settings ( const char *string ) {
 | 
		
	
		
			
			| 1597 | 1621 |  		tail = ( end + 1 );
 | 
		
	
		
			
			| 1598 | 1622 |  
 | 
		
	
		
			
			| 1599 | 1623 |  		/* Determine setting length */
 | 
		
	
		
			
			| 1600 |  | -		setting_len = fetchf_named_setting ( name, NULL, 0 );
 | 
		
	
		
			
			|  | 1624 | +		setting_len = fetchf_named_setting ( name, NULL, 0, NULL, 0 );
 | 
		
	
		
			
			| 1601 | 1625 |  		if ( setting_len < 0 )
 | 
		
	
		
			
			| 1602 | 1626 |  			setting_len = 0; /* Treat error as empty setting */
 | 
		
	
		
			
			| 1603 | 1627 |  
 | 
		
	
	
		
			
			|  | @@ -1606,7 +1630,7 @@ char * expand_settings ( const char *string ) {
 | 
		
	
		
			
			| 1606 | 1630 |  			char setting_buf[ setting_len + 1 ];
 | 
		
	
		
			
			| 1607 | 1631 |  
 | 
		
	
		
			
			| 1608 | 1632 |  			setting_buf[0] = '\0';
 | 
		
	
		
			
			| 1609 |  | -			fetchf_named_setting ( name, setting_buf,
 | 
		
	
		
			
			|  | 1633 | +			fetchf_named_setting ( name, NULL, 0, setting_buf,
 | 
		
	
		
			
			| 1610 | 1634 |  					       sizeof ( setting_buf ) );
 | 
		
	
		
			
			| 1611 | 1635 |  
 | 
		
	
		
			
			| 1612 | 1636 |  			/* Construct expanded string and discard old string */
 |