Subject: bin/15464: Make can't uppercase or lowercase variable contents.
To: None <gnats-bugs@gnats.netbsd.org>
From: None <kpn@neutralgood.org>
List: netbsd-bugs
Date: 02/02/2002 16:41:57
>Number:         15464
>Category:       bin
>Synopsis:       Make can't uppercase or lowercase variable contents.
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    bin-bug-people
>State:          open
>Class:          change-request
>Submitter-Id:   net
>Arrival-Date:   Sat Feb 02 13:43:00 PST 2002
>Closed-Date:
>Last-Modified:
>Originator:     Kevin P. Neal
>Release:        NetBSD 1.5.2
>Organization:
-- 
Kevin P. Neal                                http://www.pobox.com/~kpn/

"You know, I think I can hear the machine screaming from here...  \
'help me! hellpp meeee!'"  - Heather Flanagan, 14:52:23 Wed Jun 10 1998
>Environment:

NetBSD-current tree as of yesterday (I think).

>Description:

There is no modifier in NetBSD make to uppercase or lowercase a variable's
contents. 

>How-To-Repeat:

Attempt to port a makefile from FreeBSD to NetBSD. 

>Fix:

Here's a patch to make/var.c from yesterday to add the "tu" and
"tl" modifiers. Modifier names OK'd on tech-toolchain. Below this
is a patch to the man page. 

*** var.c.orig	Sat Feb  2 15:41:05 2002
--- var.c	Sat Feb  2 15:58:05 2002
***************
*** 216,225 ****
--- 216,226 ----
  static Boolean VarLoopExpand __P((GNode *, char *, Boolean, Buffer,
  				  ClientData));
  static char *VarGetPattern __P((GNode *, int, char **, int, int *, int *,
  				VarPattern *));
  static char *VarQuote __P((char *));
+ static char *VarChangeCase __P((char *, int));
  static char *VarModify __P((GNode *, char *, Boolean (*)(GNode *, char *,
  							 Boolean, Buffer,
  							 ClientData),
  			    ClientData));
  static char *VarSort __P((char *));
***************
*** 1598,1607 ****
--- 1599,1639 ----
      str = (char *)Buf_GetAll (buf, (int *)NULL);
      Buf_Destroy (buf, FALSE);
      return str;
  }
  
+ /*-
+  *-----------------------------------------------------------------------
+  * VarChangeCase --
+  *      Change the string to all uppercase or all lowercase
+  *
+  * Results:
+  *      The string with case changed
+  *
+  * Side Effects:
+  *      None.
+  *
+  *-----------------------------------------------------------------------
+  */
+ static char *
+ VarChangeCase(str, upper)
+         char *str;                  /* String to modify */
+         int upper;                  /* TRUE -> uppercase, else lowercase */
+ {
+    Buffer         buf;
+    int            (*modProc) __P((int));
+ 
+    modProc = (upper ? toupper : tolower);
+    buf = Buf_Init (MAKE_BSIZE);
+    for (; *str ; str++) {
+        Buf_AddByte(buf, (Byte) modProc(*str));
+    }
+    Buf_AddByte(buf, (Byte) '\0');
+    str = (char *) Buf_GetAll (buf, (int *) NULL);
+    Buf_Destroy (buf, FALSE);
+    return str;
+ }
  
  /*-
   *-----------------------------------------------------------------------
   * Var_Parse --
   *	Given the start of a variable invocation, extract the variable
***************
*** 1913,1922 ****
--- 1945,1956 ----
       *  	  	    	each word
       *  	  :R	    	Substitute the root of each word
       *  	  	    	(pathname minus the suffix).
       *		  :O		("Order") Sort words in variable.
       *		  :u		("uniq") Remove adjacent duplicate words.
+      *		  :tu		Converts the variable contents to uppercase.
+      *		  :tl		Converts the variable contents to lowercase.
       *		  :?<true-value>:<false-value>
       *				If the variable evaluates to true, return
       *				true value, else return the second value.
       *	    	  :lhs=rhs  	Like :S, but the rhs goes to the end of
       *	    	    	    	the invocation.
***************
*** 2184,2193 ****
--- 2218,2240 ----
  			Error (emsg, str);
  		    termc = *cp;
  		    delim = '\0';
  		    if (v->flags & VAR_JUNK) {
  			v->flags |= VAR_KEEP;
+ 		    }
+ 		    break;
+ 		}
+ 	        case 't':
+ 		{
+ 		    if (tstr[1] != endc && tstr[1] != ':') {
+ 		        if (tstr[2] == endc || tstr[2] == ':') {
+                             if (tstr[1] == 'u' || tstr[1] == 'l') {
+                                 newStr = VarChangeCase (str, (tstr[1] == 'u'));
+                                 cp = tstr + 2;
+                                 termc = *cp;
+                             }
+ 		        }
  		    }
  		    break;
  		}
  		case 'N':
  		case 'M':


*** make.1.orig	Sat Feb  2 16:15:36 2002
--- make.1	Sat Feb  2 16:39:34 2002
***************
*** 581,590 ****
--- 581,594 ----
  Quotes every shell meta-character in the variable, so that it can be passed
  safely through recursive invocations of
  .Nm "" .
  .It Cm R
  Replaces each word in the variable with everything but its suffix.
+ .It Cm tl
+ Converts variable to lower-case letters.
+ .It Cm tu
+ Converts variable to upper-case letters.
  .Sm off
  .It Cm S No \&/ Ar old_string Xo
  .No \&/ Ar new_string
  .No \&/ Op Cm 1g
  .Xc
>Release-Note:
>Audit-Trail:
>Unformatted: