1################################################################################
2#
3# This file contains various utility macros and variables used about
4# everywhere in make constructs.
5#
6################################################################################
7
8# Strip quotes and then whitespaces
9qstrip = $(strip $(subst ",,$(1)))
10#"))
11
12# Variables for use in Make constructs
13comma := ,
14empty :=
15space := $(empty) $(empty)
16tab := $(empty)	$(empty)
17escape := $(shell printf '\x1b')
18
19# make 4.3:
20# https://lwn.net/Articles/810071/
21# Number signs (#) appearing inside a macro reference or function invocation
22#   no longer introduce comments and should not be escaped with backslashes:
23#   thus a call such as:
24#     foo := $(shell echo '#')
25#   is legal.  Previously the number sign needed to be escaped, for example:
26#     foo := $(shell echo '\#')
27#   Now this latter will resolve to "\#".  If you want to write makefiles
28#   portable to both versions, assign the number sign to a variable:
29#     H := \#
30#     foo := $(shell echo '$H')
31SHARP_SIGN := \#
32
33# Case conversion macros. This is inspired by the 'up' macro from gmsl
34# (http://gmsl.sf.net). It is optimised very heavily because these macros
35# are used a lot. It is about 5 times faster than forking a shell and tr.
36#
37# The caseconvert-helper creates a definition of the case conversion macro.
38# After expansion by the outer $(eval ), the UPPERCASE macro is defined as:
39# $(strip $(eval __tmp := $(1))  $(eval __tmp := $(subst a,A,$(__tmp))) ... )
40# In other words, every letter is substituted one by one.
41#
42# The caseconvert-helper allows us to create this definition out of the
43# [FROM] and [TO] lists, so we don't need to write down every substition
44# manually. The uses of $ and $$ quoting are chosen in order to do as
45# much expansion as possible up-front.
46#
47# Note that it would be possible to conceive a slightly more optimal
48# implementation that avoids the use of __tmp, but that would be even
49# more unreadable and is not worth the effort.
50
51[FROM] := 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 - .
52[TO]   := 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 _ _
53
54define caseconvert-helper
55$(1) = $$(strip \
56	$$(eval __tmp := $$(1))\
57	$(foreach c, $(2),\
58		$$(eval __tmp := $$(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$$(__tmp))))\
59	$$(__tmp))
60endef
61
62$(eval $(call caseconvert-helper,UPPERCASE,$(join $(addsuffix :,$([FROM])),$([TO]))))
63$(eval $(call caseconvert-helper,LOWERCASE,$(join $(addsuffix :,$([TO])),$([FROM]))))
64
65# Reverse the orders of words in a list. Again, inspired by the gmsl
66# 'reverse' macro.
67reverse = $(if $(1),$(call reverse,$(wordlist 2,$(words $(1)),$(1))) $(firstword $(1)))
68
69# Sanitize macro cleans up generic strings so it can be used as a filename
70# and in rules. Particularly useful for VCS version strings, that can contain
71# slashes, colons (OK in filenames but not in rules), and spaces.
72sanitize = $(subst $(space),_,$(subst :,_,$(subst /,_,$(strip $(1)))))
73
74# MESSAGE Macro -- display a message in bold type
75MESSAGE = echo "$(TERM_BOLD)>>> $($(PKG)_NAME) $($(PKG)_VERSION) $(call qstrip,$(1))$(TERM_RESET)"
76TERM_BOLD := $(shell tput smso 2>/dev/null)
77TERM_RESET := $(shell tput rmso 2>/dev/null)
78
79# Utility functions for 'find'
80# findfileclauses(filelist) => -name 'X' -o -name 'Y'
81findfileclauses = $(call notfirstword,$(patsubst %,-o -name '%',$(1)))
82# finddirclauses(base, dirlist) => -path 'base/dirX' -o -path 'base/dirY'
83finddirclauses = $(call notfirstword,$(patsubst %,-o -path '$(1)/%',$(2)))
84
85# Miscellaneous utility functions
86# notfirstword(wordlist): returns all but the first word in wordlist
87notfirstword = $(wordlist 2,$(words $(1)),$(1))
88
89# build a comma-separated list of items, from a space-separated
90# list of items:   a b c d  -->  a, b, c, d
91make-comma-list = $(subst $(space),$(comma)$(space),$(strip $(1)))
92
93# build a comma-separated list of double-quoted items, from a space-separated
94# list of unquoted items:   a b c d  -->  "a", "b", "c", "d"
95make-dq-comma-list = $(call make-comma-list,$(patsubst %,"%",$(strip $(1))))
96
97# build a comma-separated list of single-quoted items, from a space-separated
98# list of unquoted items:   a b c d  -->  'a', 'b', 'c', 'd'
99make-sq-comma-list = $(call make-comma-list,$(patsubst %,'%',$(strip $(1))))
100
101# Needed for the foreach loops to loop over the list of hooks, so that
102# each hook call is properly separated by a newline.
103define sep
104
105
106endef
107
108PERCENT = %
109QUOTE = '
110# ' # Meh... syntax-highlighting
111
112# This macro properly escapes a command string, then prints it with printf:
113#
114#   - first, backslash '\' are self-escaped, so that they do not escape
115#     the following char and so that printf properly outputs a backslash;
116#
117#   - next, single quotes are escaped by closing an existing one, adding
118#     an escaped one, and re-openning a new one (see below for the reason);
119#
120#   - then '%' signs are self-escaped so that the printf does not interpret
121#     them as a format specifier, in case the variable contains an actual
122#     printf with a format;
123#
124#   - finally, $(sep) is replaced with the literal '\n' so that make does
125#     not break on the so-expanded variable, but so that the printf does
126#     correctly output an LF.
127#
128# Note: this must be escaped in this order to avoid over-escaping the
129# previously escaped elements.
130#
131# Once everything has been escaped, it is passed between single quotes
132# (that's why the single-quotes are escaped they way they are, above,
133# and why the dollar sign is not escaped) to printf(1). A trailing
134# newline is apended, too.
135#
136# Note: leading or trailing spaces are *not* stripped.
137#
138define PRINTF
139	printf '$(subst $(sep),\n,\
140		$(subst $(PERCENT),$(PERCENT)$(PERCENT),\
141			$(subst $(QUOTE),$(QUOTE)\$(QUOTE)$(QUOTE),\
142				$(subst \,\\,$(1)))))\n'
143endef
144