github.com/crowdsecurity/crowdsec@v1.6.1/mk/__gmsl (about) 1 # ---------------------------------------------------------------------------- 2 # 3 # GNU Make Standard Library (GMSL) 4 # 5 # A library of functions to be used with GNU Make's $(call) that 6 # provides functionality not available in standard GNU Make. 7 # 8 # Copyright (c) 2005-2022 John Graham-Cumming 9 # 10 # This file is part of GMSL 11 # 12 # Redistribution and use in source and binary forms, with or without 13 # modification, are permitted provided that the following conditions 14 # are met: 15 # 16 # Redistributions of source code must retain the above copyright 17 # notice, this list of conditions and the following disclaimer. 18 # 19 # Redistributions in binary form must reproduce the above copyright 20 # notice, this list of conditions and the following disclaimer in the 21 # documentation and/or other materials provided with the distribution. 22 # 23 # Neither the name of the John Graham-Cumming nor the names of its 24 # contributors may be used to endorse or promote products derived from 25 # this software without specific prior written permission. 26 # 27 # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 28 # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 29 # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 30 # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 31 # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 32 # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 33 # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 34 # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 35 # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 37 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 38 # POSSIBILITY OF SUCH DAMAGE. 39 # 40 # ---------------------------------------------------------------------------- 41 42 # This is the GNU Make Standard Library version number as a list with 43 # three items: major, minor, revision 44 45 gmsl_version := 1 2 0 46 47 __gmsl_name := GNU Make Standard Library 48 49 # Used to output warnings and error from the library, it's possible to 50 # disable any warnings or errors by overriding these definitions 51 # manually or by setting GMSL_NO_WARNINGS or GMSL_NO_ERRORS 52 53 ifdef GMSL_NO_WARNINGS 54 __gmsl_warning := 55 else 56 __gmsl_warning = $(if $1,$(warning $(__gmsl_name): $1)) 57 endif 58 59 ifdef GMSL_NO_ERRORS 60 __gmsl_error := 61 else 62 __gmsl_error = $(if $1,$(error $(__gmsl_name): $1)) 63 endif 64 65 # If GMSL_TRACE is enabled then calls to the library functions are 66 # traced to stdout using warning messages with their arguments 67 68 ifdef GMSL_TRACE 69 __gmsl_tr1 = $(warning $0('$1')) 70 __gmsl_tr2 = $(warning $0('$1','$2')) 71 __gmsl_tr3 = $(warning $0('$1','$2','$3')) 72 else 73 __gmsl_tr1 := 74 __gmsl_tr2 := 75 __gmsl_tr3 := 76 endif 77 78 # See if spaces are valid in variable names (this was the case until 79 # GNU Make 3.82) 80 ifeq ($(MAKE_VERSION),3.82) 81 __gmsl_spaced_vars := $(false) 82 else 83 __gmsl_spaced_vars := $(true) 84 endif 85 86 # Figure out whether we have $(eval) or not (GNU Make 3.80 and above) 87 # if we do not then output a warning message, if we do then some 88 # functions will be enabled. 89 90 __gmsl_have_eval := $(false) 91 __gmsl_ignore := $(eval __gmsl_have_eval := $(true)) 92 93 # If this is being run with Electric Cloud's emake then warn that 94 # their $(eval) support is incomplete in 1.x, 2.x, 3.x, 4.x and 5.0, 95 # 5.1, 5.2 and 5.3 96 97 ifdef ECLOUD_BUILD_ID 98 __gmsl_emake_major := $(word 1,$(subst ., ,$(EMAKE_VERSION))) 99 __gmsl_emake_minor := $(word 2,$(subst ., ,$(EMAKE_VERSION))) 100 ifneq ("$(findstring $(__gmsl_emake_major),1 2 3 4)$(findstring $(__gmsl_emake_major)$(__gmsl_emake_minor),50 51 52 53)","") 101 $(warning You are using a version of Electric Cloud's emake which has incomplete $$(eval) support) 102 __gmsl_have_eval := $(false) 103 endif 104 endif 105 106 # See if we have $(lastword) (GNU Make 3.81 and above) 107 108 __gmsl_have_lastword := $(lastword $(false) $(true)) 109 110 # See if we have native or and and (GNU Make 3.81 and above) 111 112 __or_tt := /$(or $(true),$(true))/$(or $(true),$(false))/$(or $(false),$(true))/$(or $(false),$(false))/ 113 __and_tt := /$(and $(true),$(true))/$(and $(true),$(false))/$(and $(false),$(true))/$(and $(false),$(false))/ 114 __gmsl_have_or := $(if $(filter /T/T/T//,$(__or_tt)),$(true),$(false)) 115 __gmsl_have_and := $(if $(filter /T////,$(__and_tt)),$(true),$(false)) 116 117 ifneq ($(__gmsl_have_eval),$(true)) 118 $(call __gmsl_warning,Your make version $(MAKE_VERSION) does not support $$$$(eval): some functions disabled) 119 endif 120 121 __gmsl_dollar := $$ 122 __gmsl_hash := \# 123 124 # ---------------------------------------------------------------------------- 125 # ---------------------------------------------------------------------------- 126 # Function: gmsl_compatible 127 # Arguments: List containing the desired library version number (maj min rev) 128 # Returns: $(true) if this version of the library is compatible 129 # with the requested version number, otherwise $(false) 130 # ---------------------------------------------------------------------------- 131 gmsl_compatible = $(strip \ 132 $(if $(call gt,$(word 1,$1),$(word 1,$(gmsl_version))), \ 133 $(false), \ 134 $(if $(call lt,$(word 1,$1),$(word 1,$(gmsl_version))), \ 135 $(true), \ 136 $(if $(call gt,$(word 2,$1),$(word 2,$(gmsl_version))), \ 137 $(false), \ 138 $(if $(call lt,$(word 2,$1),$(word 2,$(gmsl_version))), \ 139 $(true), \ 140 $(call lte,$(word 3,$1),$(word 3,$(gmsl_version)))))))) 141 142 # ########################################################################### 143 # LOGICAL OPERATORS 144 # ########################################################################### 145 146 # not is defined in gmsl 147 148 # ---------------------------------------------------------------------------- 149 # Function: and 150 # Arguments: Two boolean values 151 # Returns: Returns $(true) if both of the booleans are true 152 # ---------------------------------------------------------------------------- 153 ifneq ($(__gmsl_have_and),$(true)) 154 and = $(__gmsl_tr2)$(if $1,$(if $2,$(true),$(false)),$(false)) 155 endif 156 157 # ---------------------------------------------------------------------------- 158 # Function: or 159 # Arguments: Two boolean values 160 # Returns: Returns $(true) if either of the booleans is true 161 # ---------------------------------------------------------------------------- 162 ifneq ($(__gmsl_have_or),$(true)) 163 or = $(__gmsl_tr2)$(if $1$2,$(true),$(false)) 164 endif 165 166 # ---------------------------------------------------------------------------- 167 # Function: xor 168 # Arguments: Two boolean values 169 # Returns: Returns $(true) if exactly one of the booleans is true 170 # ---------------------------------------------------------------------------- 171 xor = $(__gmsl_tr2)$(if $1,$(if $2,$(false),$(true)),$(if $2,$(true),$(false))) 172 173 # ---------------------------------------------------------------------------- 174 # Function: nand 175 # Arguments: Two boolean values 176 # Returns: Returns value of 'not and' 177 # ---------------------------------------------------------------------------- 178 nand = $(__gmsl_tr2)$(if $1,$(if $2,$(false),$(true)),$(true)) 179 180 # ---------------------------------------------------------------------------- 181 # Function: nor 182 # Arguments: Two boolean values 183 # Returns: Returns value of 'not or' 184 # ---------------------------------------------------------------------------- 185 nor = $(__gmsl_tr2)$(if $1$2,$(false),$(true)) 186 187 # ---------------------------------------------------------------------------- 188 # Function: xnor 189 # Arguments: Two boolean values 190 # Returns: Returns value of 'not xor' 191 # ---------------------------------------------------------------------------- 192 xnor =$(__gmsl_tr2)$(if $1,$(if $2,$(true),$(false)),$(if $2,$(false),$(true))) 193 194 # ########################################################################### 195 # LIST MANIPULATION FUNCTIONS 196 # ########################################################################### 197 198 # ---------------------------------------------------------------------------- 199 # Function: first (same as LISP's car, or head) 200 # Arguments: 1: A list 201 # Returns: Returns the first element of a list 202 # ---------------------------------------------------------------------------- 203 first = $(__gmsl_tr1)$(firstword $1) 204 205 # ---------------------------------------------------------------------------- 206 # Function: last 207 # Arguments: 1: A list 208 # Returns: Returns the last element of a list 209 # ---------------------------------------------------------------------------- 210 ifeq ($(__gmsl_have_lastword),$(true)) 211 last = $(__gmsl_tr1)$(lastword $1) 212 else 213 last = $(__gmsl_tr1)$(if $1,$(word $(words $1),$1)) 214 endif 215 216 # ---------------------------------------------------------------------------- 217 # Function: rest (same as LISP's cdr, or tail) 218 # Arguments: 1: A list 219 # Returns: Returns the list with the first element removed 220 # ---------------------------------------------------------------------------- 221 rest = $(__gmsl_tr1)$(wordlist 2,$(words $1),$1) 222 223 # ---------------------------------------------------------------------------- 224 # Function: chop 225 # Arguments: 1: A list 226 # Returns: Returns the list with the last element removed 227 # ---------------------------------------------------------------------------- 228 chop = $(__gmsl_tr1)$(wordlist 2,$(words $1),x $1) 229 230 # ---------------------------------------------------------------------------- 231 # Function: map 232 # Arguments: 1: Name of function to $(call) for each element of list 233 # 2: List to iterate over calling the function in 1 234 # Returns: The list after calling the function on each element 235 # ---------------------------------------------------------------------------- 236 map = $(__gmsl_tr2)$(strip $(foreach a,$2,$(call $1,$a))) 237 238 # ---------------------------------------------------------------------------- 239 # Function: pairmap 240 # Arguments: 1: Name of function to $(call) for each pair of elements 241 # 2: List to iterate over calling the function in 1 242 # 3: Second list to iterate over calling the function in 1 243 # Returns: The list after calling the function on each pair of elements 244 # ---------------------------------------------------------------------------- 245 pairmap = $(strip $(__gmsl_tr3)\ 246 $(if $2$3,$(call $1,$(call first,$2),$(call first,$3)) \ 247 $(call pairmap,$1,$(call rest,$2),$(call rest,$3)))) 248 249 # ---------------------------------------------------------------------------- 250 # Function: leq 251 # Arguments: 1: A list to compare against... 252 # 2: ...this list 253 # Returns: Returns $(true) if the two lists are identical 254 # ---------------------------------------------------------------------------- 255 leq = $(__gmsl_tr2)$(strip $(if $(call seq,$(words $1),$(words $2)), \ 256 $(call __gmsl_list_equal,$1,$2),$(false))) 257 258 __gmsl_list_equal = $(if $(strip $1), \ 259 $(if $(call seq,$(call first,$1),$(call first,$2)), \ 260 $(call __gmsl_list_equal, \ 261 $(call rest,$1), \ 262 $(call rest,$2)), \ 263 $(false)), \ 264 $(true)) 265 266 # ---------------------------------------------------------------------------- 267 # Function: lne 268 # Arguments: 1: A list to compare against... 269 # 2: ...this list 270 # Returns: Returns $(true) if the two lists are different 271 # ---------------------------------------------------------------------------- 272 lne = $(__gmsl_tr2)$(call not,$(call leq,$1,$2)) 273 274 # ---------------------------------------------------------------------------- 275 # Function: reverse 276 # Arguments: 1: A list to reverse 277 # Returns: The list with its elements in reverse order 278 # ---------------------------------------------------------------------------- 279 reverse =$(__gmsl_tr1)$(strip $(if $1,$(call reverse,$(call rest,$1)) \ 280 $(call first,$1))) 281 282 # ---------------------------------------------------------------------------- 283 # Function: uniq 284 # Arguments: 1: A list from which to remove repeated elements 285 # Returns: The list with duplicate elements removed without reordering 286 # ---------------------------------------------------------------------------- 287 uniq = $(strip $(__gmsl_tr1) $(if $1,$(firstword $1) \ 288 $(call uniq,$(filter-out $(firstword $1),$1)))) 289 290 # ---------------------------------------------------------------------------- 291 # Function: length 292 # Arguments: 1: A list 293 # Returns: The number of elements in the list 294 # ---------------------------------------------------------------------------- 295 length = $(__gmsl_tr1)$(words $1) 296 297 # ########################################################################### 298 # STRING MANIPULATION FUNCTIONS 299 # ########################################################################### 300 301 # Helper function that translates any GNU Make 'true' value (i.e. a 302 # non-empty string) to our $(true) 303 304 __gmsl_make_bool = $(if $(strip $1),$(true),$(false)) 305 306 # ---------------------------------------------------------------------------- 307 # Function: seq 308 # Arguments: 1: A string to compare against... 309 # 2: ...this string 310 # Returns: Returns $(true) if the two strings are identical 311 # ---------------------------------------------------------------------------- 312 seq = $(__gmsl_tr2)$(if $(subst x$1,,x$2)$(subst x$2,,x$1),$(false),$(true)) 313 314 # ---------------------------------------------------------------------------- 315 # Function: sne 316 # Arguments: 1: A string to compare against... 317 # 2: ...this string 318 # Returns: Returns $(true) if the two strings are not the same 319 # ---------------------------------------------------------------------------- 320 sne = $(__gmsl_tr2)$(call not,$(call seq,$1,$2)) 321 322 # ---------------------------------------------------------------------------- 323 # Function: split 324 # Arguments: 1: The character to split on 325 # 2: A string to split 326 # Returns: Splits a string into a list separated by spaces at the split 327 # character in the first argument 328 # ---------------------------------------------------------------------------- 329 split = $(__gmsl_tr2)$(strip $(subst $1, ,$2)) 330 331 # ---------------------------------------------------------------------------- 332 # Function: merge 333 # Arguments: 1: The character to put between fields 334 # 2: A list to merge into a string 335 # Returns: Merges a list into a single string, list elements are separated 336 # by the character in the first argument 337 # ---------------------------------------------------------------------------- 338 merge = $(__gmsl_tr2)$(strip $(if $2, \ 339 $(if $(call seq,1,$(words $2)), \ 340 $2,$(call first,$2)$1$(call merge,$1,$(call rest,$2))))) 341 342 ifdef __gmsl_have_eval 343 # ---------------------------------------------------------------------------- 344 # Function: tr 345 # Arguments: 1: The list of characters to translate from 346 # 2: The list of characters to translate to 347 # 3: The text to translate 348 # Returns: Returns the text after translating characters 349 # ---------------------------------------------------------------------------- 350 tr = $(strip $(__gmsl_tr3)$(call assert_no_dollar,$0,$1$2$3) \ 351 $(eval __gmsl_t := $3) \ 352 $(foreach c, \ 353 $(join $(addsuffix :,$1),$2), \ 354 $(eval __gmsl_t := \ 355 $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)), \ 356 $(__gmsl_t))))$(__gmsl_t)) 357 358 # Common character classes for use with the tr function. Each of 359 # these is actually a variable declaration and must be wrapped with 360 # $() or ${} to be used. 361 362 [A-Z] := 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 # 363 [a-z] := 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 # 364 [0-9] := 0 1 2 3 4 5 6 7 8 9 # 365 [A-F] := A B C D E F # 366 367 # ---------------------------------------------------------------------------- 368 # Function: uc 369 # Arguments: 1: Text to upper case 370 # Returns: Returns the text in upper case 371 # ---------------------------------------------------------------------------- 372 uc = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call tr,$([a-z]),$([A-Z]),$1) 373 374 # ---------------------------------------------------------------------------- 375 # Function: lc 376 # Arguments: 1: Text to lower case 377 # Returns: Returns the text in lower case 378 # ---------------------------------------------------------------------------- 379 lc = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(call tr,$([A-Z]),$([a-z]),$1) 380 381 # ---------------------------------------------------------------------------- 382 # Function: strlen 383 # Arguments: 1: A string 384 # Returns: Returns the length of the string 385 # ---------------------------------------------------------------------------- 386 387 # This results in __gmsl_tab containing a tab 388 389 __gmsl_tab := # 390 391 __gmsl_characters := 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 392 __gmsl_characters += 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 393 __gmsl_characters += 0 1 2 3 4 5 6 7 8 9 394 __gmsl_characters += ` ~ ! @ \# $$ % ^ & * ( ) - _ = + 395 __gmsl_characters += { } [ ] \ : ; ' " < > , . / ? | 396 397 # This results in __gmsl_space containing just a space 398 399 __gmsl_empty := 400 __gmsl_space := $(__gmsl_empty) $(__gmsl_empty) 401 402 strlen = $(__gmsl_tr1)$(call assert_no_dollar,$0,$1)$(strip $(eval __temp := $(subst $(__gmsl_space),x,$1))$(foreach a,$(__gmsl_characters),$(eval __temp := $$(subst $$a,x,$(__temp))))$(eval __temp := $(subst x,x ,$(__temp)))$(words $(__temp))) 403 404 # This results in __gmsl_newline containing just a newline 405 406 define __gmsl_newline 407 408 409 endef 410 411 # ---------------------------------------------------------------------------- 412 # Function: substr 413 # Arguments: 1: A string 414 # 2: Start position (first character is 1) 415 # 3: End position (inclusive) 416 # Returns: A substring. 417 # Note: The string in $1 must not contain a § 418 # ---------------------------------------------------------------------------- 419 420 substr = $(if $2,$(__gmsl_tr3)$(call assert_no_dollar,$0,$1$2$3)$(strip $(eval __temp := $$(subst $$(__gmsl_space),§ ,$$1))$(foreach a,$(__gmsl_characters),$(eval __temp := $$(subst $$a,$$a$$(__gmsl_space),$(__temp))))$(eval __temp := $(wordlist $2,$3,$(__temp))))$(subst §,$(__gmsl_space),$(subst $(__gmsl_space),,$(__temp)))) 421 422 endif # __gmsl_have_eval 423 424 # ########################################################################### 425 # SET MANIPULATION FUNCTIONS 426 # ########################################################################### 427 428 # Sets are represented by sorted, deduplicated lists. To create a set 429 # from a list use set_create, or start with the empty_set and 430 # set_insert individual elements 431 432 # This is the empty set 433 empty_set := 434 435 # ---------------------------------------------------------------------------- 436 # Function: set_create 437 # Arguments: 1: A list of set elements 438 # Returns: Returns the newly created set 439 # ---------------------------------------------------------------------------- 440 set_create = $(__gmsl_tr1)$(sort $1) 441 442 # ---------------------------------------------------------------------------- 443 # Function: set_insert 444 # Arguments: 1: A single element to add to a set 445 # 2: A set 446 # Returns: Returns the set with the element added 447 # ---------------------------------------------------------------------------- 448 set_insert = $(__gmsl_tr2)$(sort $1 $2) 449 450 # ---------------------------------------------------------------------------- 451 # Function: set_remove 452 # Arguments: 1: A single element to remove from a set 453 # 2: A set 454 # Returns: Returns the set with the element removed 455 # ---------------------------------------------------------------------------- 456 set_remove = $(__gmsl_tr2)$(filter-out $1,$2) 457 458 # ---------------------------------------------------------------------------- 459 # Function: set_is_member, set_is_not_member 460 # Arguments: 1: A single element 461 # 2: A set 462 # Returns: (set_is_member) Returns $(true) if the element is in the set 463 # (set_is_not_member) Returns $(false) if the element is in the set 464 # ---------------------------------------------------------------------------- 465 set_is_member = $(__gmsl_tr2)$(if $(filter $1,$2),$(true),$(false)) 466 set_is_not_member = $(__gmsl_tr2)$(if $(filter $1,$2),$(false),$(true)) 467 468 # ---------------------------------------------------------------------------- 469 # Function: set_union 470 # Arguments: 1: A set 471 # 2: Another set 472 # Returns: Returns the union of the two sets 473 # ---------------------------------------------------------------------------- 474 set_union = $(__gmsl_tr2)$(sort $1 $2) 475 476 # ---------------------------------------------------------------------------- 477 # Function: set_intersection 478 # Arguments: 1: A set 479 # 2: Another set 480 # Returns: Returns the intersection of the two sets 481 # ---------------------------------------------------------------------------- 482 set_intersection = $(__gmsl_tr2)$(filter $1,$2) 483 484 # ---------------------------------------------------------------------------- 485 # Function: set_is_subset 486 # Arguments: 1: A set 487 # 2: Another set 488 # Returns: Returns $(true) if the first set is a subset of the second 489 # ---------------------------------------------------------------------------- 490 set_is_subset = $(__gmsl_tr2)$(call set_equal,$(call set_intersection,$1,$2),$1) 491 492 # ---------------------------------------------------------------------------- 493 # Function: set_equal 494 # Arguments: 1: A set 495 # 2: Another set 496 # Returns: Returns $(true) if the two sets are identical 497 # ---------------------------------------------------------------------------- 498 set_equal = $(__gmsl_tr2)$(call seq,$1,$2) 499 500 # ########################################################################### 501 # ARITHMETIC LIBRARY 502 # ########################################################################### 503 504 # Integers a represented by lists with the equivalent number of x's. 505 # For example the number 4 is x x x x. 506 507 # ---------------------------------------------------------------------------- 508 # Function: int_decode 509 # Arguments: 1: A number of x's representation 510 # Returns: Returns the integer for human consumption that is represented 511 # by the string of x's 512 # ---------------------------------------------------------------------------- 513 int_decode = $(__gmsl_tr1)$(if $1,$(if $(call seq,$(word 1,$1),x),$(words $1),$1),0) 514 515 # ---------------------------------------------------------------------------- 516 # Function: int_encode 517 # Arguments: 1: A number in human-readable integer form 518 # Returns: Returns the integer encoded as a string of x's 519 # ---------------------------------------------------------------------------- 520 __int_encode = $(if $1,$(if $(call seq,$(words $(wordlist 1,$1,$2)),$1),$(wordlist 1,$1,$2),$(call __int_encode,$1,$(if $2,$2 $2,x)))) 521 __strip_leading_zero = $(if $1,$(if $(call seq,$(patsubst 0%,%,$1),$1),$1,$(call __strip_leading_zero,$(patsubst 0%,%,$1))),0) 522 int_encode = $(__gmsl_tr1)$(call __int_encode,$(call __strip_leading_zero,$1)) 523 524 # The arithmetic library functions come in two forms: one form of each 525 # function takes integers as arguments and the other form takes the 526 # encoded form (x's created by a call to int_encode). For example, 527 # there are two plus functions: 528 # 529 # plus Called with integer arguments and returns an integer 530 # int_plus Called with encoded arguments and returns an encoded result 531 # 532 # plus will be slower than int_plus because its arguments and result 533 # have to be translated between the x's format and integers. If doing 534 # a complex calculation use the int_* forms with a single encoding of 535 # inputs and single decoding of the output. For simple calculations 536 # the direct forms can be used. 537 538 # Helper function used to wrap an int_* function into a function that 539 # takes a pair of integers, perhaps a function and returns an integer 540 # result 541 __gmsl_int_wrap = $(call int_decode,$(call $1,$(call int_encode,$2),$(call int_encode,$3))) 542 __gmsl_int_wrap1 = $(call int_decode,$(call $1,$(call int_encode,$2))) 543 __gmsl_int_wrap2 = $(call $1,$(call int_encode,$2),$(call int_encode,$3)) 544 545 # ---------------------------------------------------------------------------- 546 # Function: int_plus 547 # Arguments: 1: A number in x's representation 548 # 2: Another number in x's represntation 549 # Returns: Returns the sum of the two numbers in x's representation 550 # ---------------------------------------------------------------------------- 551 int_plus = $(strip $(__gmsl_tr2)$1 $2) 552 553 # ---------------------------------------------------------------------------- 554 # Function: plus (wrapped version of int_plus) 555 # Arguments: 1: An integer 556 # 2: Another integer 557 # Returns: Returns the sum of the two integers 558 # ---------------------------------------------------------------------------- 559 plus = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_plus,$1,$2) 560 561 # ---------------------------------------------------------------------------- 562 # Function: int_subtract 563 # Arguments: 1: A number in x's representation 564 # 2: Another number in x's represntation 565 # Returns: Returns the difference of the two numbers in x's representation, 566 # or outputs an error on a numeric underflow 567 # ---------------------------------------------------------------------------- 568 int_subtract = $(strip $(__gmsl_tr2)$(if $(call int_gte,$1,$2), \ 569 $(filter-out xx,$(join $1,$2)), \ 570 $(call __gmsl_warning,Subtraction underflow))) 571 572 # ---------------------------------------------------------------------------- 573 # Function: subtract (wrapped version of int_subtract) 574 # Arguments: 1: An integer 575 # 2: Another integer 576 # Returns: Returns the difference of the two integers, 577 # or outputs an error on a numeric underflow 578 # ---------------------------------------------------------------------------- 579 subtract = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_subtract,$1,$2) 580 581 # ---------------------------------------------------------------------------- 582 # Function: int_multiply 583 # Arguments: 1: A number in x's representation 584 # 2: Another number in x's represntation 585 # Returns: Returns the product of the two numbers in x's representation 586 # ---------------------------------------------------------------------------- 587 int_multiply = $(strip $(__gmsl_tr2)$(foreach a,$1,$2)) 588 589 # ---------------------------------------------------------------------------- 590 # Function: multiply (wrapped version of int_multiply) 591 # Arguments: 1: An integer 592 # 2: Another integer 593 # Returns: Returns the product of the two integers 594 # ---------------------------------------------------------------------------- 595 multiply = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_multiply,$1,$2) 596 597 # ---------------------------------------------------------------------------- 598 # Function: int_divide 599 # Arguments: 1: A number in x's representation 600 # 2: Another number in x's represntation 601 # Returns: Returns the result of integer division of argument 1 divided 602 # by argument 2 in x's representation 603 # ---------------------------------------------------------------------------- 604 int_divide = $(__gmsl_tr2)$(strip $(if $1,$(if $2, \ 605 $(subst M,x,$(filter-out x,$(subst $2,M,$1))), \ 606 $(call __gmsl_error,Division by zero)))) 607 608 # ---------------------------------------------------------------------------- 609 # Function: divide (wrapped version of int_divide) 610 # Arguments: 1: An integer 611 # 2: Another integer 612 # Returns: Returns the integer division of the first argument by the second 613 # ---------------------------------------------------------------------------- 614 divide = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_divide,$1,$2) 615 616 # ---------------------------------------------------------------------------- 617 # Function: int_modulo 618 # Arguments: 1: A number in x's representation 619 # 2: Another number in x's represntation 620 # Returns: Returns the remainder of integer division of argument 1 divided 621 # by argument 2 in x's representation 622 # ---------------------------------------------------------------------------- 623 int_modulo = $(__gmsl_tr2)$(strip $(if $1,$(if $2, \ 624 $(filter-out M,$(subst $2,M,$1)), \ 625 $(call __gmsl_error,Division by zero)))) 626 627 # ---------------------------------------------------------------------------- 628 # Function: modulo (wrapped version of int_modulo) 629 # Arguments: 1: An integer 630 # 2: Another integer 631 # Returns: Returns the remainder of integer division of the first argument 632 # by the second 633 # ---------------------------------------------------------------------------- 634 modulo = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_modulo,$1,$2) 635 636 # ---------------------------------------------------------------------------- 637 # Function: int_max, int_min 638 # Arguments: 1: A number in x's representation 639 # 2: Another number in x's represntation 640 # Returns: Returns the maximum or minimum of its arguments in x's 641 # representation 642 # ---------------------------------------------------------------------------- 643 int_max = $(__gmsl_tr2)$(subst xx,x,$(join $1,$2)) 644 int_min = $(__gmsl_tr2)$(subst xx,x,$(filter xx,$(join $1,$2))) 645 646 # ---------------------------------------------------------------------------- 647 # Function: max, min 648 # Arguments: 1: An integer 649 # 2: Another integer 650 # Returns: Returns the maximum or minimum of its integer arguments 651 # ---------------------------------------------------------------------------- 652 max = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_max,$1,$2) 653 min = $(__gmsl_tr2)$(call __gmsl_int_wrap,int_min,$1,$2) 654 655 # ---------------------------------------------------------------------------- 656 # Function: int_gt, int_gte, int_lt, int_lte, int_eq, int_ne 657 # Arguments: Two x's representation numbers to be compared 658 # Returns: $(true) or $(false) 659 # 660 # int_gt First argument greater than second argument 661 # int_gte First argument greater than or equal to second argument 662 # int_lt First argument less than second argument 663 # int_lte First argument less than or equal to second argument 664 # int_eq First argument is numerically equal to the second argument 665 # int_ne First argument is not numerically equal to the second argument 666 # ---------------------------------------------------------------------------- 667 int_gt = $(__gmsl_tr2)$(call __gmsl_make_bool, \ 668 $(filter-out $(words $2), \ 669 $(words $(call int_max,$1,$2)))) 670 int_gte = $(__gmsl_tr2)$(call __gmsl_make_bool, \ 671 $(call int_gt,$1,$2)$(call int_eq,$1,$2)) 672 int_lt = $(__gmsl_tr2)$(call __gmsl_make_bool, \ 673 $(filter-out $(words $1), \ 674 $(words $(call int_max,$1,$2)))) 675 int_lte = $(__gmsl_tr2)$(call __gmsl_make_bool, \ 676 $(call int_lt,$1,$2)$(call int_eq,$1,$2)) 677 int_eq = $(__gmsl_tr2)$(call __gmsl_make_bool, \ 678 $(filter $(words $1),$(words $2))) 679 int_ne = $(__gmsl_tr2)$(call __gmsl_make_bool, \ 680 $(filter-out $(words $1),$(words $2))) 681 682 # ---------------------------------------------------------------------------- 683 # Function: gt, gte, lt, lte, eq, ne 684 # Arguments: Two integers to be compared 685 # Returns: $(true) or $(false) 686 # 687 # gt First argument greater than second argument 688 # gte First argument greater than or equal to second argument 689 # lt First argument less than second argument 690 # lte First argument less than or equal to second argument 691 # eq First argument is numerically equal to the second argument 692 # ne First argument is not numerically equal to the second argument 693 # ---------------------------------------------------------------------------- 694 gt = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_gt,$1,$2) 695 gte = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_gte,$1,$2) 696 lt = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_lt,$1,$2) 697 lte = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_lte,$1,$2) 698 eq = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_eq,$1,$2) 699 ne = $(__gmsl_tr2)$(call __gmsl_int_wrap2,int_ne,$1,$2) 700 701 # increment adds 1 to its argument, decrement subtracts 1. Note that 702 # decrement does not range check and hence will not underflow, but 703 # will incorrectly say that 0 - 1 = 0 704 705 # ---------------------------------------------------------------------------- 706 # Function: int_inc 707 # Arguments: 1: A number in x's representation 708 # Returns: The number incremented by 1 in x's representation 709 # ---------------------------------------------------------------------------- 710 int_inc = $(strip $(__gmsl_tr1)$1 x) 711 712 # ---------------------------------------------------------------------------- 713 # Function: inc 714 # Arguments: 1: An integer 715 # Returns: The argument incremented by 1 716 # ---------------------------------------------------------------------------- 717 inc = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_inc,$1) 718 719 # ---------------------------------------------------------------------------- 720 # Function: int_dec 721 # Arguments: 1: A number in x's representation 722 # Returns: The number decremented by 1 in x's representation 723 # ---------------------------------------------------------------------------- 724 int_dec = $(__gmsl_tr1)$(strip \ 725 $(if $(call sne,0,$(words $1)), \ 726 $(wordlist 2,$(words $1),$1))) 727 728 # ---------------------------------------------------------------------------- 729 # Function: dec 730 # Arguments: 1: An integer 731 # Returns: The argument decremented by 1 732 # ---------------------------------------------------------------------------- 733 dec = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_dec,$1) 734 735 # double doubles its argument, and halve halves it 736 737 # ---------------------------------------------------------------------------- 738 # Function: int_double 739 # Arguments: 1: A number in x's representation 740 # Returns: The number doubled (i.e. * 2) and returned in x's representation 741 # ---------------------------------------------------------------------------- 742 int_double = $(strip $(__gmsl_tr1)$1 $1) 743 744 # ---------------------------------------------------------------------------- 745 # Function: double 746 # Arguments: 1: An integer 747 # Returns: The integer times 2 748 # ---------------------------------------------------------------------------- 749 double = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_double,$1) 750 751 # ---------------------------------------------------------------------------- 752 # Function: int_halve 753 # Arguments: 1: A number in x's representation 754 # Returns: The number halved (i.e. / 2) and returned in x's representation 755 # ---------------------------------------------------------------------------- 756 int_halve = $(__gmsl_tr1)$(strip $(subst xx,x,$(filter-out xy x y, \ 757 $(join $1,$(foreach a,$1,y x))))) 758 759 # ---------------------------------------------------------------------------- 760 # Function: halve 761 # Arguments: 1: An integer 762 # Returns: The integer divided by 2 763 # ---------------------------------------------------------------------------- 764 halve = $(__gmsl_tr1)$(call __gmsl_int_wrap1,int_halve,$1) 765 766 # ---------------------------------------------------------------------------- 767 # Function: sequence 768 # Arguments: 1: An integer 769 # 2: An integer 770 # Returns: The sequence [arg1, arg2] of integers if arg1 < arg2 or 771 # [arg2, arg1] if arg2 > arg1. If arg1 == arg1 return [arg1] 772 # ---------------------------------------------------------------------------- 773 sequence = $(__gmsl_tr2)$(strip $(if $(call lte,$1,$2), \ 774 $(call __gmsl_sequence_up,$1,$2), \ 775 $(call __gmsl_sequence_dn,$2,$1))) 776 777 __gmsl_sequence_up = $(if $(call seq,$1,$2),$1,$1 $(call __gmsl_sequence_up,$(call inc,$1),$2)) 778 __gmsl_sequence_dn = $(if $(call seq,$1,$2),$1,$2 $(call __gmsl_sequence_dn,$1,$(call dec,$2))) 779 780 # ---------------------------------------------------------------------------- 781 # Function: dec2hex, dec2bin, dec2oct 782 # Arguments: 1: An integer 783 # Returns: The decimal argument converted to hexadecimal, binary or 784 # octal 785 # ---------------------------------------------------------------------------- 786 787 __gmsl_digit = $(subst 15,f,$(subst 14,e,$(subst 13,d,$(subst 12,c,$(subst 11,b,$(subst 10,a,$1)))))) 788 789 dec2hex = $(call __gmsl_dec2base,$(call int_encode,$1),$(call int_encode,16)) 790 dec2bin = $(call __gmsl_dec2base,$(call int_encode,$1),$(call int_encode,2)) 791 dec2oct = $(call __gmsl_dec2base,$(call int_encode,$1),$(call int_encode,8)) 792 793 __gmsl_base_divide = $(subst $2,X ,$1) 794 __gmsl_q = $(strip $(filter X,$1)) 795 __gmsl_r = $(words $(filter x,$1)) 796 797 __gmsl_dec2base = $(eval __gmsl_temp := $(call __gmsl_base_divide,$1,$2))$(call __gmsl_dec2base_,$(call __gmsl_q,$(__gmsl_temp)),$(call __gmsl_r,$(__gmsl_temp)),$2) 798 __gmsl_dec2base_ = $(if $1,$(call __gmsl_dec2base,$(subst X,x,$1),$3))$(call __gmsl_digit,$2) 799 800 ifdef __gmsl_have_eval 801 # ########################################################################### 802 # ASSOCIATIVE ARRAYS 803 # ########################################################################### 804 805 # Magic string that is very unlikely to appear in a key or value 806 807 __gmsl_aa_magic := faf192c8efbc25c27992c5bc5add390393d583c6 808 809 # ---------------------------------------------------------------------------- 810 # Function: set 811 # Arguments: 1: Name of associative array 812 # 2: The key value to associate 813 # 3: The value associated with the key 814 # Returns: Nothing 815 # ---------------------------------------------------------------------------- 816 set = $(__gmsl_tr3)$(call assert_no_space,$0,$1$2)$(call assert_no_dollar,$0,$1$2$3)$(eval __gmsl_aa_$1_$(__gmsl_aa_magic)_$2_gmsl_aa_$1 := $3) 817 818 # Only used internally by memoize function 819 820 __gmsl_set = $(call set,$1,$2,$3)$3 821 822 # ---------------------------------------------------------------------------- 823 # Function: get 824 # Arguments: 1: Name of associative array 825 # 2: The key to retrieve 826 # Returns: The value stored in the array for that key 827 # ---------------------------------------------------------------------------- 828 get = $(strip $(__gmsl_tr2)$(call assert_no_space,$0,$1$2)$(call assert_no_dollar,$0,$1$2)$(__gmsl_aa_$1_$(__gmsl_aa_magic)_$2_gmsl_aa_$1)) 829 830 # ---------------------------------------------------------------------------- 831 # Function: keys 832 # Arguments: 1: Name of associative array 833 # Returns: Returns a list of all defined keys in the array 834 # ---------------------------------------------------------------------------- 835 keys = $(__gmsl_tr1)$(call assert_no_space,$0,$1)$(call assert_no_dollar,$0,$1)$(sort $(patsubst __gmsl_aa_$1_$(__gmsl_aa_magic)_%_gmsl_aa_$1,%, \ 836 $(filter __gmsl_aa_$1_$(__gmsl_aa_magic)_%_gmsl_aa_$1,$(.VARIABLES)))) 837 838 # ---------------------------------------------------------------------------- 839 # Function: defined 840 # Arguments: 1: Name of associative array 841 # 2: The key to test 842 # Returns: Returns true if the key is defined (i.e. not empty) 843 # ---------------------------------------------------------------------------- 844 defined = $(__gmsl_tr2)$(call assert_no_space,$0,$1$2)$(call assert_no_dollar,$0,$1$2)$(call sne,$(call get,$1,$2),) 845 846 endif # __gmsl_have_eval 847 848 ifdef __gmsl_have_eval 849 # ########################################################################### 850 # NAMED STACKS 851 # ########################################################################### 852 853 # ---------------------------------------------------------------------------- 854 # Function: push 855 # Arguments: 1: Name of stack 856 # 2: Value to push onto the top of the stack (must not contain 857 # a space) 858 # Returns: None 859 # ---------------------------------------------------------------------------- 860 push = $(__gmsl_tr2)$(call assert_no_space,$0,$1$2)$(call assert_no_dollar,$0,$1$2)$(eval __gmsl_stack_$1 := $2 $(if $(filter-out undefined,\ 861 $(origin __gmsl_stack_$1)),$(__gmsl_stack_$1))) 862 863 # ---------------------------------------------------------------------------- 864 # Function: pop 865 # Arguments: 1: Name of stack 866 # Returns: Top element from the stack after removing it 867 # ---------------------------------------------------------------------------- 868 pop = $(__gmsl_tr1)$(call assert_no_space,$0,$1)$(call assert_no_dollar,$0,$1)$(strip $(if $(filter-out undefined,$(origin __gmsl_stack_$1)), \ 869 $(call first,$(__gmsl_stack_$1)) \ 870 $(eval __gmsl_stack_$1 := $(call rest,$(__gmsl_stack_$1))))) 871 872 # ---------------------------------------------------------------------------- 873 # Function: peek 874 # Arguments: 1: Name of stack 875 # Returns: Top element from the stack without removing it 876 # ---------------------------------------------------------------------------- 877 peek = $(__gmsl_tr1)$(call assert_no_space,$0,$1)$(call assert_no_dollar,$0,$1)$(call first,$(__gmsl_stack_$1)) 878 879 # ---------------------------------------------------------------------------- 880 # Function: depth 881 # Arguments: 1: Name of stack 882 # Returns: Number of items on the stack 883 # ---------------------------------------------------------------------------- 884 depth = $(__gmsl_tr1)$(call assert_no_space,$0,$1)$(call assert_no_dollar,$0,$1)$(words $(__gmsl_stack_$1)) 885 886 endif # __gmsl_have_eval 887 888 ifdef __gmsl_have_eval 889 # ########################################################################### 890 # STRING CACHE 891 # ########################################################################### 892 893 # ---------------------------------------------------------------------------- 894 # Function: memoize 895 # Arguments: 1. Name of the function to be called if the string 896 # has not been previously seen 897 # 2. A string 898 # Returns: Returns the result of a memo function (which the user must 899 # define) on the passed in string and remembers the result. 900 # 901 # Example: Set memo = $(shell echo "$1" | md5sum) to make a cache 902 # of MD5 hashes of strings. $(call memoize,memo,foo bar baz) 903 # ---------------------------------------------------------------------------- 904 __gmsl_memoize = $(subst $(__gmsl_space),§,$1)cc2af1bb7c4482f2ba75e338b963d3e7$(subst $(__gmsl_space),§,$2) 905 memoize = $(__gmsl_tr2)$(strip $(if $(call defined,__gmsl_m,$(__gmsl_memoize)),\ 906 $(call get,__gmsl_m,$(__gmsl_memoize)), \ 907 $(call __gmsl_set,__gmsl_m,$(__gmsl_memoize),$(call $1,$2)))) 908 909 endif # __gmsl_have_eval 910 911 # ########################################################################### 912 # DEBUGGING FACILITIES 913 # ########################################################################### 914 915 # ---------------------------------------------------------------------------- 916 # Target: gmsl-echo-% 917 # Arguments: The % should be replaced by the name of a variable that you 918 # wish to print out. 919 # Action: Echos the value of the variable that matches the %. 920 # For example, 'make gmsl-echo-SHELL' will output the value of 921 # the SHELL variable. 922 # ---------------------------------------------------------------------------- 923 gmsl-echo-%: ; @echo $($*) 924 925 # ---------------------------------------------------------------------------- 926 # Target: gmsl-print-% 927 # Arguments: The % should be replaced by the name of a variable that you 928 # wish to print out. 929 # Action: Echos the name of the variable that matches the % and its value. 930 # For example, 'make gmsl-print-SHELL' will output the value of 931 # the SHELL variable 932 # ---------------------------------------------------------------------------- 933 gmsl-print-%: ; @echo $* = $($*) 934 935 # ---------------------------------------------------------------------------- 936 # Function: assert 937 # Arguments: 1: A boolean that must be true or the assertion will fail 938 # 2: The message to print with the assertion 939 # Returns: None 940 # ---------------------------------------------------------------------------- 941 assert = $(if $2,$(if $1,,$(call __gmsl_error,Assertion failure: $2))) 942 943 # ---------------------------------------------------------------------------- 944 # Function: assert_exists 945 # Arguments: 1: Name of file that must exist, if it is missing an assertion 946 # will be generated 947 # Returns: None 948 # ---------------------------------------------------------------------------- 949 assert_exists = $(if $0,$(call assert,$(wildcard $1),file '$1' missing)) 950 951 # ---------------------------------------------------------------------------- 952 # Function: assert_no_dollar 953 # Arguments: 1: Name of a function being executd 954 # 2: Arguments to check 955 # Returns: None 956 # ---------------------------------------------------------------------------- 957 assert_no_dollar = $(call __gmsl_tr2)$(call assert,$(call not,$(findstring $(__gmsl_dollar),$2)),$1 called with a dollar sign in argument) 958 959 # ---------------------------------------------------------------------------- 960 # Function: assert_no_space 961 # Arguments: 1: Name of a function being executd 962 # 2: Arguments to check 963 # Returns: None 964 # ---------------------------------------------------------------------------- 965 ifeq ($(__gmsl_spaced_vars),$(false)) 966 assert_no_space = $(call assert,$(call not,$(findstring $(__gmsl_aa_magic),$(subst $(__gmsl_space),$(__gmsl_aa_magic),$2))),$1 called with a space in argument) 967 else 968 assert_no_space = 969 endif