Makefile:12: *** missing separator. Stop. gfortran - makefile

F90 = gfortran
FFLAGS = #-O3, this is an optimizer which makes loops more efficient
EXECUTABLE = quad
# Object Files for build
OBJS = \
Constants.o \
functions.o \
quadratureRules.o \
$(EXECUTABLE) : $(OBJS)
$(F90) $(FFLAGS) -o $(EXECUTABLE) ./QuadExample.f90 $(OBJS)
# Object dependencies and compilation
Constants.o : ./Constants.f90
$(F90) $(FFLAGS) -c ./Constants.f90
functions.o : ./functions.f90 \
Constants.o
$(F90) $(FFLAGS) -c ./functions.f90
quadratureRules.o : ./quadratureRules.f90 \
Constants.o
$(F90) $(FFLAGS) -c ./quadratureRules.f90
# Utility targets
.PHONY: clean
clean:
rm *.o *.mod
rm quad
I was trying to compile the Fortran code as listed in Fortran Andrew R. Winters notes. I am listing the version here in case these notes disappear from the web.
But when running make to build these files, I got the following error
Makefile:12: *** missing separator. Stop.
After seeing the other make file questions, I sort of felt that the problem was due to Sublime Text transforming my tabs to spaces as I had initially set it up to do. (For python). I did not want to disturb that.
I tried to detect where the tabs were supposed to be but it sort of gave mixed results
Like I could not figure out what the ^M meant.
Then I tried .editorconfig file approach to tell Sublime Text to not fix tabs automagically. Also to no avail.
I also tried an answer that said use the u09 Unicode character, I can't find it now.
I am reproducing the files
Constants.f90 functions.f90 QuadExample.f90 quadratureRules.f90
below for better idea
Constants.f90
MODULE Constants
IMPLICIT NONE
INTEGER ,PARAMETER :: RP = SELECTED_REAL_KIND(15)
REAL(KIND=RP),PARAMETER :: pi = 4.0_RP*ATAN(1.0_RP)
END MODULE Constants
functions.f90
FUNCTION f(x)
IMPLICIT NONE
INTEGER,PARAMETER :: RP = SELECTED_REAL_KIND(15)
REAL(KIND=RP),INTENT(IN) :: x
REAL(KIND=RP) :: f
!
f = EXP(x) - x**2 ! Alternatively could use x*x, faster than the "power" command
!
END FUNCTION f
!
FUNCTION g(x)
IMPLICIT NONE
INTEGER,PARAMETER :: RP = SELECTED_REAL_KIND(15)
REAL(KIND=RP),INTENT(IN) :: x
REAL(KIND=RP) :: g
!
g = SIN(x) - COS(x)
!
END FUNCTION g
QuadExample.f90
PROGRAM Quadrature
IMPLICIT NONE
INTEGER ,PARAMETER :: RP = SELECTED_REAL_KIND(15)
INTEGER ,PARAMETER :: N = 150
REAL(KIND=RP),PARAMETER :: a = -1.0_RP, b = 2.0_RP
REAL(KIND=RP) :: Integral
REAL(KIND=RP),EXTERNAL :: leftHandRule,f,g
!
WRITE(*,*)
Integral = lefthandRule(a,b,N,f)
WRITE(*,*) 'Approximation for f(x) integral: ',Integral
WRITE(*,*)
Integral = leftHandRule(a,b,N,g)
WRITE(*,*)'Approximation for g(x) integral: ',Integral
!
END PROGRAM Quadrature
quadratureRules.f90
FUNCTION leftHandRule(a,b,N,func)
IMPLICIT NONE
INTEGER ,PARAMETER :: RP = SELECTED_REAL_KIND(15)
INTEGER ,INTENT(IN) :: N
REAL(KIND=RP),INTENT(IN) :: a,b
REAL(KIND=RP),EXTERNAL :: func
REAL(KIND=RP) :: leftHandRule
! Local Variables
INTEGER :: i
REAL(KIND=RP) :: dx,x
!
dx = (b-a)/N
leftHandRule = 0.0_RP
DO i = 0,N-1
x = a + i*dx
leftHandRule = leftHandRule + func(x)*dx
END DO! i
!
END FUNCTION leftHandRule

Inspired by an answer relating to gedit
I opened Sublime Text> Preferences > Settings
and added "Makefile" to "file_exclude_patterns":
After that, I opened it I gedit and actually converted spaces to tabs.
Voila things worked.

Related

Blas function return 2 different result when compiled with relative path and absolute path

I have a very weird problem when I compile Fortran code using the zgerc subroutine from BLAS. Basically, this subroutine calculate the outer product of vector x with the conjugate of vector y. More about that function here. My simple code is as following:
program main
implicit none
integer :: i
complex(8), dimension(10) :: a = [(i, i=0,9)]
complex(8), dimension(10) :: b = [(i, i=0,9)]
complex(8), dimension(10, 10) :: c
c = 0
CALL zgerc(10, 10, 1.D0, a, 1, b, 1, c, 10)
WRITE(*, *) c
end program main
I have here 2 complex vectors, a and b, both goes from 0 to 9 and their imaginary part is 0.
Now for the weird part. If I compile that code with absolute path: gfortran -c /home/myUser/Fortran/tests/main.f90 -o main.o I get the correct result, but if I compile with gfortran -c main.f90 -o main.o (of course I'm in the right directory, and I've also tried ./main.f90) the result of the real part is correct, but for the imaginary part I get numbers like 1E+225 (and if I use ./main.f90 I get numbers like 1E+163).
I can't understand why the path to my code change the result of the imaginary part... I'll be glad for your help.
I use Ubuntu 20.04.2 with the default gfortran (9.3.0)
P.S, my final goal is to use this as part of a more complex subroutine in Python with f2py.
EDIT: my full commands:
#gfortran -c /home/myUser/Fortran/tests/main.f90 -o main.o
gfortran -c main.f90 -o main.o
gfortran -o test main.o /home/myUser/PycharmProjects/GSIE_2D/fortran_scripts/libblas.a /home/myUser/PycharmProjects/GSIE_2D/fortran_scripts/liblapack.a
rm ./main.o
./test
line 1 and 2 are the 2 cases, so I run only one of them each time.
You supply 1d0 which is a double precision literal whereas zgerc assumes a double complex value.
call zgerc(10, 10, cmplx(1, kind=8), a, 1, b, 1, c, 10)
By including explicit interfaces (via some kind of blas module) you would have gotten compile time errors when supplying arguments of wrong data type.
Intel's mkl provides such explicit interfaces in its blas95 module as well as generic routines (gerc instead of {c,z}gerc).
There is also this open-source module providing explicit interfaces to standard blas routines.
Also make use of the portable types defined in iso_fortran_env.
program main
use blas95, only: gerc
use iso_fortran_env, only: real64
implicit none
integer, parameter :: n = 10
integer :: i
complex(real64) :: a(n) = [(i, i=0,n-1)], b(n) = [(i, i=0,n-1)], c(n,n)
c = 0
! call zgerc(10, 10, cmplx(1, kind=8), a, 1, b, 1, c, 10) ! standard blas
call gerc(c, a, b, alpha=cmplx(1, kind=real64)) ! generic blas95
print *, c
end program

Calling string manipulation functions in Makefile returns empty variable [duplicate]

This is a silly question, but.... with GNU Make:
VAR = MixedCaseText
LOWER_VAR = $(VAR,lc)
default:
#echo $(VAR)
#echo $(LOWER_VAR)
In the above example, what's the correct syntax for converting VAR's contents to lower case? The syntax shown (and everything else I've run across) result in LOWER_VAR being an empty string.
you can always spawn off tr
LOWER_VAR = `echo $(VAR) | tr A-Z a-z`
or
LOWER_VAR = $(shell echo $(VAR) | tr A-Z a-z)
The 'lc' functions you trying to call is from GNU Make Standard Library
Assuming that is installed , the proper syntax would be
LOWER_VAR = $(call lc,$(VAR))
You can do this directly in gmake, without using the GNU Make Standard Library:
lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
VAR = MixedCaseText
LOWER_VAR = $(call lc,$(VAR))
all:
#echo $(VAR)
#echo $(LOWER_VAR)
It looks a little clunky, but it gets the job done.
If you do go with the $(shell) variety, please do use := instead of just =, as in LOWER_VAR := $(shell echo $VAR | tr A-Z a-z). That way, you only invoke the shell one time, when the variable is declared, instead of every time the variable is referenced!
To handle capital letters with accents:
LOWER_VAR = $(shell echo $VAR | tr '[:upper:]' '[:lower:]')
Results:
$ VAR="Éclipse"
$ echo $VAR | tr A-Z a-z
Éclipse
$ echo $VAR | tr '[:upper:]' '[:lower:]'
éclipse
I find this slightly cleaner...
$(shell tr '[:upper:]' '[:lower:]' <<< $(VAR))
If Python is installed this runs even on Windows:
$(shell python -c "print('$(VAR)'.lower())")
GNU make doesn't include string functions for case conversion. Thus, there is no lc function defined, by default.
But GNU Make usually comes with GNU Guile support enabled (e.g. this is the case on Fedora 33).
Thus, you can just call a Guile function for converting the case:
VAR = MixedCaseText
LOWER_VAR = $(guile (string-downcase "$(VAR)"))
default:
#echo $(VAR)
#echo $(LOWER_VAR)
Or if you want to encapsulate the Guile call:
VAR = MixedCaseText
LOWER_VAR = $(call to_lower,$(VAR))
define to_lower
$(guile (string-downcase "$(1)"))
endef
default:
#echo $(VAR)
#echo $(LOWER_VAR)
I wrote this while looking for a solution.
It is a bit verbose but believe it explains the steps and keeps really long lines out on the Makefile.
You can easily be modify it to perform any substitution you may want.
Hope it helps someone.
# set the separator for the *_TABLE variables, needed as otherwise `$(addprefix ...)` fails
luc_JOIN ::= ,
# define the upper and lower cased characters
lc_CHARS ::= a b c d e f g h i j k l m n o p q r s t u v w x y z
uc_CHARS ::= A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
# join the above to create the *_TABLE variables (i.e `a,A b,B ...`, `A,a B,b ...`)
lc_TABLE ::= $(join $(uc_CHARS),$(addprefix $(luc_JOIN),$(lc_CHARS)))
uc_TABLE ::= $(join $(lc_CHARS),$(addprefix $(luc_JOIN),$(uc_CHARS)))
# an internal macro to recursively create `$(subst ...)` from provided *_TABLE and string, (e.g. `$(subst a,A,$(subst b,B,...))`)
luc_internal = $(if $1,$$(subst $(firstword $1),$(call luc_internal,$(wordlist 2,$(words $1),$1),$2)),$2)
# the actual macros to $(call ...), which calls the luc_internal with the correct *_TABLE
lc = $(eval lc_RESULT ::= $(call luc_internal,$(lc_TABLE),$1))$(lc_RESULT)
uc = $(eval uc_RESULT ::= $(call luc_internal,$(uc_TABLE),$1))$(uc_RESULT)
# a mixed case value
VAR = SOME text
default:
#echo $(call lc,$(VAR))
#echo $(call uc,$(VAR))
Being impressed by the Eric Melski answer, I was curious how make handles recursion (I'm looking at you C preprocessor). Somewhat more involved, than original answer, but it's fascinating what a 50 years old tool can do. Not saying you should use this code, but I guess you could.
pop2 = $(wordlist 3,$(words $(1)),$(1))
sub1 = $(subst $(word 1,$(1)),$(word 2,$(1)),$(2))
map = $(if $(1),$(call sub1,$(1),$(call map,$(call pop2,$(1)),$(2))),$(2))
upperMap := a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
upper = $(call map,$(upperMap),$(1))
lowerMap := A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z
lower = $(call map,$(lowerMap),$(1))
#Usage:
x := $(call upper,AaBbCcDdEe)

Segmentation Fault from Fortran shared object

I have a fortran subroutine in the file gfunc.f90. I want to call this subroutine from my main program in test.f90.
If I keep both files in the same directory and compile them with
gfortran gfunc.f90 test.f90 -o test
It works fine.
But I want the subroutine to be in a library. Thus, I create a subfolder called gfunc/ and put gfunc.f90 there. In that folder, I compile the module with
gfortran -fdefault-real-8 -fPIC -c gfunc.f90
and
gfortran -fdefault-real-8 -shared -o gfunc.so gfunc.o
I now compile the main program with
gfortran test.f90 gfunc/gfunc.so
But now I get a segmentation fault as soon as a variable in the subroutine is accessed.
How do I have to compile and link the library correctly?
Here, you find a minimal working example in order to reproduce the problem:
gfunc.f90:
module gfunc_module
implicit none
contains
subroutine gfunc(x, n, m, a, b, c)
double precision, intent(in) :: x
integer, intent(in) :: n, m
double precision, dimension(n), intent(in) :: a
double precision, dimension(m), intent(in) :: b
double precision, dimension(n, m), intent(out) :: c
integer :: i, j
do j=1,m
do i=1,n
c(i,j) = exp(-x * (a(i)**2 + b(j)**2))
end do
end do
end subroutine
end module
test.f90:
program main
use gfunc_module
implicit none
integer, parameter :: dp = kind(1.0d0)
real(dp) :: x = 1.
integer, parameter :: n = 4
integer, parameter :: m = 4
real(dp), dimension(n) :: a = [-1., -0.33333333, .033333333, 1.]
real(dp), dimension(m) :: b = [-1., -0.33333333, .033333333, 1.]
real(dp), dimension(n, m) :: c
call gfunc(x, n, m, a, b, c)
write(*,*) c
end program main
You should add fdefault-real-8 to your compilation of test.f90:
gfortran -fdefault-real-8 test.f90 gfunc/gfunc.so
From the documentation for gfortran -fdefault-real-8 is making DOUBLE PRECISION variables 16 bytes wide, so without it on test.f90 the double precision variables are only 8 bytes wide:
-fdefault-real-8
Set the default real type to an 8 byte wide type. Do nothing if this is already the default. This option also affects the kind of non-double real constants like 1.0, and does promote the default width of "DOUBLE PRECISION" to 16 bytes if possible, unless "-fdefault-double-8" is given, too.

Makefile: find function which returns position [duplicate]

In my makefile, I need to make a variable assignment based on a command line variable value. for example, I do:
make var_1=xxx
where var_1 can have one of say 100 possible values. Based on the value of var_1, I need to assign a value to var_2 in my makefile. I could do:
ifeq ($(var_1), a)
var_2 = A
endif
ifeq ($(var_1), b)
var_2 = B
endif
and so on for all 100 possible combinations of var_1, var_2. Here a,A,b,B represent some strings. How do I do this to avoid 100's of if statements? I was thinking to define two variables:
var_1_values = a b c d
var_2_values = A B C D
I can use $(findstring $(var_1),$(var_1_values)) to see if $(var_1) is among $(var_1_values), but how do I locate the position of $(var_1) among all $(var_1_values)? That position is then to be used to pick the corresponding word inside $(var_2_values).
It's a little kludgey, but if there's a symbol you know won't be in any of the values (such as "_") you could do this:
var_1_values = a b c d
var_2_values = A B C D
# This will be a_A b_B c_C d_D
LIST1 = $(join $(addsuffix _,$(var_1_values)),$(var_2_values))
var_1 := a
# The filter gives a_A, the subst turns it into A
var_2 = $(subst $(var_1)_,,$(filter $(var_1)_%, $(LIST1)))
This can be done quite slickly using recursion inside GNU make functions as follows:
_pos = $(if $(findstring $1,$2),$(call _pos,$1,\
$(wordlist 2,$(words $2),$2),x $3),$3)
pos = $(words $(call _pos,$1,$2))
To use it you would $(call) the pos function with two arguments: the item to find and the list to find it in. For example,
$(call pos,a,a b c d e f g)
$(call pos,e,a b c d e f g)
$(call pos,g,a b c d e f g)
$(call pos,h,a b c d e f g)
$(call pos,e,))
It works by recursing through the $2 argument until it can no longer find the value in $1. Each time it recurses it lops the head off $2 using $(wordlist 2,$(words $2),$2). Each time is recurses it adds an x to the returned string so that there is one x for each position through $2 up to where $1 was found.
It then just uses $(words) to count the length of the return from _pos (the number of xs).
If you use the GMSL project this can be written more slickly write this as:
_pos = $(if $(findstring $1,$2),$(call $0,$1,$(call rest,$2),x $3),$3)
pos = $(words $(call _$0,$1,$2))
Note that I used $0 here which will contain the name of the current function (that's a standard GNU make feature) and the GMSL function rest to lop the head off the list.
There's a smooth way to do this using recursion as follows. First define a function called pos that finds the position of an element in a list and then use $(word) to extract the corresponding element in another list.
Here's pos:
_pos = $(if $(findstring $1,$2),$(call _pos,$1,\
$(wordlist 2,$(words $2),$2),x $3),$3)
pos = $(words $(call _pos,$1,$2))
Read this answer to understand how it works: Makefile: find function which returns position
Now it's easy to define a function that finds an element in a list and the finds the corresponding element in another list.
lookup = $(word $(call pos,$1,$2),$3)
And then try if out like this:
ALPHA := a b c d e f g h i j k l m n o p q r s t u v w x y z
NATO := alpha beta charlie delta echo foxtrot gamma hotel india\
juliet kilo lima mike november oscar papa quebec romeo\
sierra tango uniform victor whisky yankee zulu
to-nato = $(call lookup,$1,$(ALPHA),$(NATO))
To make a to-nato function that converts from a letter of the alphabet to the NATO alphabet.
One way simulate associative containers in make is to use computed variables. E.g.:
var_2.a := A
var_2.b := B
# ...
# lookup
var_2 = ${var_2.${var_1}}
# or, lookup and assign a default value if lookup fails
var_2_or_default = $(or ${var_2.${var_1}},<default-value>)
FAB = macrofab
# NOTE: base starts at 1 instead of 0
none := 1
seeed := 1
oshpark := 2
macrofab := 2
pcbng := 3
#NOTE: String must end with a space for word function to work
SUFFIX_DRILLS := "txt xln drl "
.PHONY: gerber
gerber:
#echo $(FAB) drill suffix is $(word $($(FAB)), $(SUFFIX_DRILLS))
Output of make is:
macrofab drill suffix is xln
This works in mingw gnu make 4.3 :
define get_index
$(shell \
$(eval _c = 1)\
$(eval _b = n n) \
$(foreach x,$(2), \
$(eval _b += n \
$(eval _c = $(words $(_b)) \
$(if $(filter $(1),$(x)), \
$(eval _r = $(_c)))))) \
echo $(_r) \
$(eval _c =) \
$(eval _b =) \
$(eval _r =) \
)
endef
Takes two arguments; the word to search for and the list where to search.
The index is 'returned' by echoing in $(shell ...)
Example:
list = cow horse chicken
index = $(call get_index,horse,$(list))
#echo $(index)
# output: 2

In GNU Make, how do I convert a variable to lower case?

This is a silly question, but.... with GNU Make:
VAR = MixedCaseText
LOWER_VAR = $(VAR,lc)
default:
#echo $(VAR)
#echo $(LOWER_VAR)
In the above example, what's the correct syntax for converting VAR's contents to lower case? The syntax shown (and everything else I've run across) result in LOWER_VAR being an empty string.
you can always spawn off tr
LOWER_VAR = `echo $(VAR) | tr A-Z a-z`
or
LOWER_VAR = $(shell echo $(VAR) | tr A-Z a-z)
The 'lc' functions you trying to call is from GNU Make Standard Library
Assuming that is installed , the proper syntax would be
LOWER_VAR = $(call lc,$(VAR))
You can do this directly in gmake, without using the GNU Make Standard Library:
lc = $(subst A,a,$(subst B,b,$(subst C,c,$(subst D,d,$(subst E,e,$(subst F,f,$(subst G,g,$(subst H,h,$(subst I,i,$(subst J,j,$(subst K,k,$(subst L,l,$(subst M,m,$(subst N,n,$(subst O,o,$(subst P,p,$(subst Q,q,$(subst R,r,$(subst S,s,$(subst T,t,$(subst U,u,$(subst V,v,$(subst W,w,$(subst X,x,$(subst Y,y,$(subst Z,z,$1))))))))))))))))))))))))))
VAR = MixedCaseText
LOWER_VAR = $(call lc,$(VAR))
all:
#echo $(VAR)
#echo $(LOWER_VAR)
It looks a little clunky, but it gets the job done.
If you do go with the $(shell) variety, please do use := instead of just =, as in LOWER_VAR := $(shell echo $VAR | tr A-Z a-z). That way, you only invoke the shell one time, when the variable is declared, instead of every time the variable is referenced!
To handle capital letters with accents:
LOWER_VAR = $(shell echo $VAR | tr '[:upper:]' '[:lower:]')
Results:
$ VAR="Éclipse"
$ echo $VAR | tr A-Z a-z
Éclipse
$ echo $VAR | tr '[:upper:]' '[:lower:]'
éclipse
I find this slightly cleaner...
$(shell tr '[:upper:]' '[:lower:]' <<< $(VAR))
If Python is installed this runs even on Windows:
$(shell python -c "print('$(VAR)'.lower())")
GNU make doesn't include string functions for case conversion. Thus, there is no lc function defined, by default.
But GNU Make usually comes with GNU Guile support enabled (e.g. this is the case on Fedora 33).
Thus, you can just call a Guile function for converting the case:
VAR = MixedCaseText
LOWER_VAR = $(guile (string-downcase "$(VAR)"))
default:
#echo $(VAR)
#echo $(LOWER_VAR)
Or if you want to encapsulate the Guile call:
VAR = MixedCaseText
LOWER_VAR = $(call to_lower,$(VAR))
define to_lower
$(guile (string-downcase "$(1)"))
endef
default:
#echo $(VAR)
#echo $(LOWER_VAR)
I wrote this while looking for a solution.
It is a bit verbose but believe it explains the steps and keeps really long lines out on the Makefile.
You can easily be modify it to perform any substitution you may want.
Hope it helps someone.
# set the separator for the *_TABLE variables, needed as otherwise `$(addprefix ...)` fails
luc_JOIN ::= ,
# define the upper and lower cased characters
lc_CHARS ::= a b c d e f g h i j k l m n o p q r s t u v w x y z
uc_CHARS ::= A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
# join the above to create the *_TABLE variables (i.e `a,A b,B ...`, `A,a B,b ...`)
lc_TABLE ::= $(join $(uc_CHARS),$(addprefix $(luc_JOIN),$(lc_CHARS)))
uc_TABLE ::= $(join $(lc_CHARS),$(addprefix $(luc_JOIN),$(uc_CHARS)))
# an internal macro to recursively create `$(subst ...)` from provided *_TABLE and string, (e.g. `$(subst a,A,$(subst b,B,...))`)
luc_internal = $(if $1,$$(subst $(firstword $1),$(call luc_internal,$(wordlist 2,$(words $1),$1),$2)),$2)
# the actual macros to $(call ...), which calls the luc_internal with the correct *_TABLE
lc = $(eval lc_RESULT ::= $(call luc_internal,$(lc_TABLE),$1))$(lc_RESULT)
uc = $(eval uc_RESULT ::= $(call luc_internal,$(uc_TABLE),$1))$(uc_RESULT)
# a mixed case value
VAR = SOME text
default:
#echo $(call lc,$(VAR))
#echo $(call uc,$(VAR))
Being impressed by the Eric Melski answer, I was curious how make handles recursion (I'm looking at you C preprocessor). Somewhat more involved, than original answer, but it's fascinating what a 50 years old tool can do. Not saying you should use this code, but I guess you could.
pop2 = $(wordlist 3,$(words $(1)),$(1))
sub1 = $(subst $(word 1,$(1)),$(word 2,$(1)),$(2))
map = $(if $(1),$(call sub1,$(1),$(call map,$(call pop2,$(1)),$(2))),$(2))
upperMap := a A b B c C d D e E f F g G h H i I j J k K l L m M n N o O p P q Q r R s S t T u U v V w W x X y Y z Z
upper = $(call map,$(upperMap),$(1))
lowerMap := A a B b C c D d E e F f G g H h I i J j K k L l M m N n O o P p Q q R r S s T t U u V v W w X x Y y Z z
lower = $(call map,$(lowerMap),$(1))
#Usage:
x := $(call upper,AaBbCcDdEe)

Resources