tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

make: new modifyer :Y



About year and a half ago I proposed to add to make(1) a function
that checks a value for "YES" or "NO" case-insensitively and returns 1
or 0 in order to avoid using ugly constructions like
!empty(varname:M[Yy][Ee][Ss]) in Makefiles and replace them with
something shorter and more maintainable.

http://mail-index.netbsd.org/tech-userlevel/2009/03/25/msg001953.html

After some discussion it was decided that adding new expression is not
feasible and David Holland proposed to add :istrue modifier. Later he
rejected his own idea in favour of general function support in bmake.

Since then neither function support nor typed values appeared in bmake,
so, I'd like to raise that question again.  I still want to avoid
constructions like !empty(varname:M[Yy][Ee][Ss]) or
${varname:U:tl} == "yes".

Taking into account how often we check variables for YES/1/NO/0 values
I've implemented variable modifier :Y in C. In short, with a help of
this modifier we can rewrite the code


  .if !empty(MKXXX:M[Yy][Ee][Ss])
  .endif

or

  .if empty(MKXXX:M[Nn][Oo])
  .endif

with a more elegant

  .if ${MKXXX:Y}
  .endif

Find the patch in the attachment. Objections?

Index: make.1
===================================================================
RCS file: /cvsroot/src/usr.bin/make/make.1,v
retrieving revision 1.195
diff -u -r1.195 make.1
--- make.1      28 Aug 2011 03:54:07 -0000      1.195
+++ make.1      6 Nov 2011 17:19:43 -0000
@@ -1274,6 +1274,13 @@
 is the value.
 If no such node exists or its path is null, then the
 name of the variable is used.
+.It Cm \&:Y
+If the variable is undefined, empty string, "0" or "no", return value is "0".
+If it is equal to "yes" or "1", return value is "1".
+Otherwise
+.Nm
+exits with error.
+Comparison is case-insensitive.
 .Sm off
 .It Cm \&:\&! Ar cmd Cm \&!
 .Sm on
Index: var.c
===================================================================
RCS file: /cvsroot/src/usr.bin/make/var.c,v
retrieving revision 1.167
diff -u -r1.167 var.c
--- var.c       3 Jun 2011 21:10:42 -0000       1.167
+++ var.c       6 Nov 2011 17:19:43 -0000
@@ -2382,6 +2382,29 @@
     return bmake_strdup(buf);
 }
 
+static char *
+VarIsYes(char *str)
+{
+    if (tolower((unsigned char) str [0]) == 'y' &&
+       tolower((unsigned char) str [1]) == 'e' &&
+       tolower((unsigned char) str [2]) == 's' &&
+       str [3] == 0)
+    {
+       return bmake_strdup("1");
+    }else if (tolower((unsigned char) str [0]) == 'n' &&
+             tolower((unsigned char) str [1]) == 'o' &&
+             str [2] == 0)
+    {
+       return bmake_strdup("0");
+    }else if (str [0] == 0){
+       return bmake_strdup("0");;
+    }else if ((str [0] == '1' || str [0] == '0') && str [1] == 0){
+       return bmake_strdup(str);
+    }else{
+       return NULL;
+    }
+}
+
 /*
  * Now we need to apply any modifiers the user wants applied.
  * These are:
@@ -2746,6 +2769,17 @@
                termc = *tstr;
                break;
            }
+       case 'Y':
+           {
+               if ((v->flags & VAR_JUNK) != 0)
+                   v->flags |= VAR_KEEP;
+               newStr = VarIsYes(nstr);
+               if (!newStr)
+                   Fatal("Bad boolean value (%s) of variable %s", nstr, 
v->name);
+               cp = ++tstr;
+               termc = *tstr;
+               break;
+           }
        case 'P':
            {
                GNode *gn;
-- 
Best regards, Aleksey Cheusov.


Home | Main Index | Thread Index | Old Index