changeset 4558:fc58084df7b5 HEAD

Negative offsets count from the end of the string. Patch by Johannes Berg.
author Timo Sirainen <tss@iki.fi>
date Thu, 10 Aug 2006 23:22:40 +0300
parents 3da066d844ea
children 4d2c4bb02c81
files doc/variables.txt src/lib/var-expand.c
diffstat 2 files changed, 27 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/doc/variables.txt	Thu Aug 10 22:44:19 2006 +0300
+++ b/doc/variables.txt	Thu Aug 10 23:22:40 2006 +0300
@@ -35,7 +35,10 @@
 You can take a substring of the variable by giving optional offset followed
 by '.' and width after the '%' character. For example %2u gives first two
 characters of the username. %2.1u gives third character of the username. If
-offset points outside the value, empty string is returned.
+the offset is negative, it counts from the end, for example %-2.02i gives
+the UID mod 100 (last two characters of the UID printed in a string). If a
+positive offset points outside the value, empty string is returned, if a
+negative offset does then the string is taken from the start.
 
 For login_log_format_elements there are also these variables:
 
--- a/src/lib/var-expand.c	Thu Aug 10 22:44:19 2006 +0300
+++ b/src/lib/var-expand.c	Thu Aug 10 23:22:40 2006 +0300
@@ -11,7 +11,8 @@
 #include <stdlib.h>
 
 struct var_expand_context {
-	unsigned int offset, width;
+	int offset;
+	unsigned int width;
 };
 
 struct var_expand_modifier {
@@ -71,7 +72,7 @@
 	}
 
 	str_printfa(hash, "%x", value);
-	while (str_len(hash) < ctx->offset)
+	while ((int)str_len(hash) < ctx->offset)
 		str_insert(hash, 0, "0");
         ctx->offset = 0;
 
@@ -109,6 +110,7 @@
 	const char *(*modifier[MAX_MODIFIER_COUNT])
 		(const char *, struct var_expand_context *);
 	unsigned int i, modifier_count;
+	int sign = 1;
 	bool zero_padding = FALSE;
 
 	memset(&ctx, 0, sizeof(ctx));
@@ -120,6 +122,10 @@
 
 			/* [<offset>.]<width>[<modifiers>]<variable> */
 			ctx.width = 0;
+			if (*str == '-') {
+				sign = -1;
+				str++;
+			}
 			if (*str == '0') {
 				zero_padding = TRUE;
 				str++;
@@ -132,7 +138,7 @@
 			if (*str != '.')
 				ctx.offset = 0;
 			else {
-				ctx.offset = ctx.width;
+				ctx.offset = sign * (int)ctx.width;
 				ctx.width = 0;
 				str++;
 				while (*str >= '0' && *str <= '9') {
@@ -178,9 +184,19 @@
 			if (var != NULL) {
 				for (i = 0; i < modifier_count; i++)
 					var = modifier[i](var, &ctx);
-				while (*var != '\0' && ctx.offset > 0) {
-					ctx.offset--;
-					var++;
+
+				if (ctx.offset < 0) {
+					/* if offset is < 0 then we want to
+					   start at the end */
+					size_t len = strlen(var);
+
+					if (len > (size_t)-ctx.offset)
+						var += len + ctx.offset;
+				} else {
+					while (*var != '\0' && ctx.offset > 0) {
+						ctx.offset--;
+						var++;
+					}
 				}
 				if (ctx.width == 0)
 					str_append(dest, var);
@@ -205,7 +221,7 @@
 	const struct var_expand_modifier *m;
 
 	/* [<offset>.]<width>[<modifiers>]<variable> */
-	while (*str >= '0' && *str <= '9')
+	while ((*str >= '0' && *str <= '9') || *str == '-')
 		str++;
 
 	if (*str == '.') {