1#!/bin/sh 2# 3# This script is used to derive compiler flags and filesystem paths 4# necessary to utilize Lua, LuaJIT, and particular versions thereof in both 5# simple and mixed installation environments. 6# 7# For usage help information use the -h switch. 8# 9# This script attempts to adhere strictly to POSIX shell specifications. The 10# known non-POSIX features used are the path of the shell at the very first 11# line of this script, the default compiler command name of `cc' instead of 12# `c99', and the use of /dev/urandom for generating a random sandbox 13# directory suffix. All of these can be override. For any other issues 14# please contact the author. 15# 16# WARNING: When searching for a Lua interpreter this script may execute 17# various utilities in an attempt to deduce their fitness and release 18# version. By default this script will search for and execute utilities 19# using the glob patterns luac* and lua*. But this script CANNOT GUARANTEE 20# that executing such utilities, or any other utilities, either wittingly or 21# unwittingly, will not result in your COMPUTER EXPLODING. You have been 22# warned. 23# 24# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 25# 26# Changelog: 27# 28# * 2013-08-02 - Published. Derived from an earlier script, lua.path, 29# written for the cqueues project. 30# 31# * 2013-08-05 - Redirect stdin from /dev/null when probing so we don't 32# freeze if a utility tries to read from stdin. 33# 34# chdir to a read-only directory by default to try to prevent creation 35# of temporary files. These features address the issues of LuaTeX 36# reading from stdin and creating a luatex.out file in the current 37# working directory. By default a directory with a random suffix 38# generated from /dev/urandom is placed in TMPDIR and removed on exit. 39# 40# If CPPFLAGS is empty and no -I options directly specified then set 41# INCDIRS to "/usr/include:/usr/local/include". 42# 43# * 2013-08-07 - Add pkg-config support and refactor header probing to delay 44# recursive searching. 45# 46# * 2013-09-09 - NetBSD's sh gets upset over the noclobber option and 47# redirection to /dev/null, so use append operator. And check $# 48# before iterating over a null parameter set with `do X; ... done` 49# when `set -u` is enabled--it complains about $@ being unset. 50# 51# * 2013-10-22 - Initial ldflags detection. 52# 53# * 2014-01-26 - Migrate CC vendor detection from external script. 54# 55# * 2014-09-29 - Add ldir and cdir modes which print install path by parsing 56# package.path and package.cpath. 57# 58# * 2014-12-18 - Add -e GLOB option. 59# 60# Deprecate ldir and cdir modes. 61# 62# Add package.path and package.cpath to replace ldir and dir modes. 63# Optional arguments to the new modes are preferred install paths, 64# rather than globs for finding the lua utility path (use the new -e 65# option, instead). 66# 67# * 2014-12-19 - Fix pkg-config version matching. The --modversion of 68# the lua package might be stale. For example, it's 5.2.0 on Ubuntu 69# 14.04 even though the Lua release is 5.2.3. 70# 71# Use the interpreter path as a reference point when searching for 72# headers. $(dirname ${LUA_PATH})/../include is a very likely location 73# as bindir and includedir have the same prefix in most installations. 74# 75# * 2015-01-15 - Quote more command names and arguments. Still need to 76# handle space characters in code that employs command substitution. I 77# think we could handle all whitespace characters, including newlines, 78# by using a control character in IFS and using --exec printf "%s\1" {} 79# rather than -print with find(1). 80# 81# * 2015-01-19 - Add fix for LuaJIT's default package.cpath, which tends to 82# hardcode /usr/local/lib/lua/5.1, ordered before the LuaJIT 83# installation prefix. 84# 85# * 2015-07-14 - Add recursive glob function implemented in shell code 86# and use instead of find(1). 87# 88# * 2016-03-18 - Fix bug in tryluac where a continue statement was used 89# instead of return 0. 90# 91# * 2016-03-25 - Support ${CC} values with trailing flags, which invoke 92# the compiler through env(1), or which otherwise are intended to 93# expand as multiple words. 94# 95# OpenBSD 5.8 sh does not suppress strict errors within an eval 96# invoked from an if condition compound-list. Workaround by changing 97# trylua to return 0 on matching failure, like tryluainclude and 98# tryluac do. 99# 100# Undeprecate ldir and cdir. The names are more intuitive and 101# convenient as evidenced by the fact that I keep using them instead 102# of package.path and package.cpath. Try to maintain backwards 103# compatibility by using a simple heuristic to differentiate lua 104# interpreter glob patterns from preferred install directory 105# string.match expressions. 106# 107# * 2016-10-10 - Fix issue with passing empty CPPFLAGS to ${CC}. /usr/bin/cc 108# in NetBSD 7.0.1 does not tolerate an empty string argument. This 109# exposed a bug in NetBSD's and FreeBSD's /bin/sh, triggered by how we 110# pass CPPFLAGS (see evalmacro and runcc routines, below). 111# 112# Some Ash variants (confirmed /bin/sh in NetBSD 7.0.1 and FreeBSD 113# 10.1) will expand unquoted ${UNSET-} and ${UNSET:-} as an empty 114# string rather than eliding it during argument processing. That is, 115# 116# nargs() { printf "%d\n" "$#"; } 117# nargs ${UNSET} 2 3 118# nargs ${UNSET-} 2 3 119# 120# prints "2" and "3", whereas every other shell tested prints "2" and 121# "2" (confirmed dash in Ubuntu Xenial; bash 4.3 in Ubuntu Xenial; 122# pdksh in FreeBSD 10.1, NetBSD 7.0, OS X 10.1, OpenBSD 6.0; ksh93 in 123# Solaris 11.3 and AIX 7.1; ksh88 in AIX 7.1). 124# 125# A workaround in set -u mode (where unbound variable expansion aborts 126# execution) is to substitute a known empty value. E.g. 127# 128# EMPTY= 129# nargs ${UNSET-$EMPTY} 130# 131# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 132# 133# Copyright (C) 2012-2016 William Ahern 134# 135# Permission is hereby granted, free of charge, to any person obtaining a 136# copy of this software and associated documentation files (the "Software"), 137# to deal in the Software without restriction, including without limitation 138# the rights to use, copy, modify, merge, publish, distribute, sublicense, 139# and/or sell copies of the Software, and to permit persons to whom the 140# Software is furnished to do so, subject to the following conditions: 141# 142# The above copyright notice and this permission notice shall be included in 143# all copies or substantial portions of the Software. 144# 145# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 146# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 147# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 148# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 149# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 150# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 151# DEALINGS IN THE SOFTWARE. 152# 153set -e # strict errors 154set -u # don't expand unbound variables 155set -f # disable pathname expansion 156set -C # noclobber 157\unalias -a # no command surprises 158export LC_ALL=C # no locale headaches 159unset IFS # no field splitting surprises 160: ${TMPDIR:=/tmp} # sane TMPDIR 161: ${CC:=cc} 162unset LUA_PATH || true # interferes search for module install directory 163unset LUA_CPATH || true 164 165MYVERSION=20161010 166MYVENDOR="william@25thandClement.com" 167 168 169EMPTY= # empty string for parameter expansion workaround for Ash bug 170DEVRANDOM=/dev/urandom 171SANDBOX="${TMPDIR}/${0##*/}-" 172 173CPPDIRS= # -I directories from CPPFLAGS 174INCDIRS= 175LDDIRS= # -L directories from LDFLAGS 176LIBDIRS= 177BINDIRS= 178RECURSE=no 179MAXDEPTH=5 # maximum recursion depth 180SHORTEST= # continue searching until shortest pathname found 181PKGCONFIG= # path to pkg-config, found by `command -v` when -k option invoked 182GLOB= # -e GLOB expression for lua, luac, ldir, and cdir 183 184GLOB_LUA="lua:lua[5-9]*:lua-[5-9]*:luajit*" 185GLOB_LUAC="luac:luac[5-9]*:luac-[5-9]*" 186 187API_MIN=500 188API_MAX=999 189API_VER= 190API_DIR= 191 192JIT_REQ= 193JIT_MIN=20000 194JIT_MAX=99999 195JIT_VER= 196JIT_DIR= 197 198LIBLUA_VER= 199LIBLUA_DIR= 200LIBLUA_LIB= 201 202LIBJIT_VER= 203LIBJIT_DIR= 204LIBJIT_LIB= 205 206LUAC_PATH= 207LUAC_VER= 208 209LUA_PATH= 210LUA_VER= 211 212 213# 214# warn FORMAT [...] 215# 216# Print message to original stderr. 217# 218exec 9>&2 219warn() { 220 printf "%s: %.0s${1}\n" "${0##*/}" "$@" >&9 221} 222 223# 224# panic FORMAT [...] 225# 226# Print message to original stderr, then exit with failure. 227# 228panic() { 229 warn "$@" 230 exit 1 231} 232 233 234# 235# parse CPPFLAGS -I or LDFLAGS -L directories 236# 237xdirs() { 238 OPTC="${1:-I}" 239 DIRS= 240 241 set -- ${2:-} 242 243 while [ $# -gt 0 ]; do 244 case "${1}" in 245 -${OPTC}) 246 shift 247 248 if [ -n "${1:-}" ]; then 249 DIRS="${DIRS}${DIRS:+:}${1}" 250 fi 251 252 ;; 253 -${OPTC}*) 254 if [ "${1}" != "-${OPTC}" ]; then 255 DIRS="${DIRS}${DIRS:+:}${1#-${OPTC}}" 256 fi 257 258 ;; 259 esac 260 261 shift 262 done 263 264 printf -- "${DIRS}" 265} 266 267idirs() { 268 xdirs "I" "${1:-}" 269} 270 271ldirs() { 272 xdirs "L" "${1:-}" 273} 274 275# count ":"-delimited substrings 276count() { 277 IFS=: 278 set -- ${1:-} 279 unset IFS 280 281 printf "$#" 282} 283 284# append to ":"-delimited string variable 285append() { 286 NAME=${1} 287 eval VALUE="\${${NAME}}" 288 shift 289 290 IFS=: 291 TMP="$*" 292 293 IFS="\n" 294 read -r "${NAME}" <<-EOF 295 ${VALUE:-}${VALUE:+:}${TMP} 296 EOF 297 unset IFS 298} 299 300# 301# glob PATTERN [MAXDEPTH] [EXEC-COMMAND] [INTERNAL:GLOB-COUNT] 302# 303glob() { 304 glob_N="${4:-0}" 305 306 IFS= 307 set +f 308 for F in ${1}; do 309 [ -e "${F}" ] || continue 310 if eval "${3:-printf '%s\\n'} \"\${F}\""; then 311 glob_N=$((${glob_N} + 1)) 312 fi 313 done 314 set -f 315 unset IFS 316 317 if [ "${2-0}" -gt 0 ]; then 318 glob "${1%/*}/*/${1##*/}" "$((${2} - 1))" "${3:-}" "${glob_N}" || : 319 fi 320 321 [ "${glob_N}" -gt 0 ] 322} # glob 323 324 325# 326# runcc [...] 327# 328# Wrapper for invoking ${CC}. Some build system include flags in ${CC}, 329# invoke the compiler through env(1), or employ other hacks. 330# 331# TODO: Optionally handle unescaping of words in a manner similar to how 332# ${CC} would be evaluated from a make rule--typically by being passed 333# through system(3). 334# 335runcc() { 336 (unset IFS; exec ${CC} "$@") 337} 338 339 340# 341# evalmacro PATH MACRO [REGEX] [SUBST] 342# 343# PATH Header identifier--#include <PATH> 344# MACRO Macro identifier 345# REGEX Optional regex pattern to match macro evaluation result 346# SUBST Optional replacement expression 347# 348evalmacro() { 349 printf "#include <$1>\n[===[$2]===]\n" \ 350 | runcc ${CPPFLAGS:-${EMPTY}} -E - 2>>/dev/null \ 351 | sed -ne " 352 s/^.*\\[===\\[ *\\(${3:-.*}\\) *\\]===\\].*$/${4:-\\1}/ 353 t Found 354 d 355 :Found 356 p 357 q 358 " 359} 360 361 362# 363# testsym PATH NAME 364# 365# Test whether global symbol NAME exists in object file at PATH. Exits with 366# 0 (true) when found, non-0 (false) otherwise. 367# 368testsym() { 369 # NOTE: No -P for OpenBSD nm(1), but the default output format is 370 # close enough. Section types always have a leading and trailing 371 # space. U section type means undefined. On AIX [VWZ] are weak 372 # global symbols. Solaris and OS X have additional symbol types 373 # beyond the canonical POSIX/BSD types, all of which are uppercase 374 # and within [A-T]. 375 (nm -Pg ${1} 2>>/dev/null || nm -g 2>>/dev/null) \ 376 | sed -ne '/ [A-T] /p' \ 377 | grep -q "${2}" 378} 379 380 381tryluainclude() { 382 V="$(evalmacro "${1}" LUA_VERSION_NUM '[0123456789][0123456789]*')" 383 : ${V:=0} 384 385 if [ "${1%/*}" != "${1}" ]; then 386 D="${1%/*}" 387 388 # cleanup after Solaris directory prune trick 389 if [ "${D##*/./}" != "${D}" ]; then 390 D="${D%%/./*}/${D##*/./}" 391 else 392 D="${D%/.}" 393 fi 394 else 395 D= 396 fi 397 398 [ "$V" -gt 0 -a "$V" -ge "${API_VER:-0}" ] || return 0 399 400 [ "$V" -gt "${API_VER:-0}" -o "${#D}" -lt "${#API_DIR}" -o \( "${JIT_REQ}" = "yes" -a "${JIT_VER:-0}" -lt "${JIT_MAX}" \) ] || return 0 401 402 [ "$V" -ge "${API_MIN}" -a "$V" -le "${API_MAX}" ] || return 0 403 404 if [ -n "${JIT_REQ}" ]; then 405 J="$(evalmacro "${1%%lua.h}luajit.h" LUAJIT_VERSION_NUM '[0123456789][0123456789]*')" 406 : ${J:=0} 407 408 if [ "${JIT_REQ}" = "skip" ]; then 409 [ "${J}" -eq 0 ] || return 0 410 elif [ "${JIT_REQ}" = "yes" ]; then 411 [ "$J" -ge "${JIT_VER:-0}" ] || return 0 412 [ "$J" -gt "${JIT_VER:-0}" -o "${#D}" -lt "${#JIT_DIR}" ] || return 0 413 [ "$J" -ge ${JIT_MIN} ] || return 0 414 [ "$J" -le "${JIT_MAX}" ] || return 0 415 416 JIT_VER="$J" 417 JIT_DIR="$D" 418 fi 419 fi 420 421 API_VER="$V" 422 API_DIR="$D" 423} 424 425 426# 427# foundversion 428# 429# true if found the best (maximum) possible version, false otherwise 430# 431foundversion() { 432 if [ "${API_VER:-0}" -lt "${API_MAX}" ]; then 433 return 1 434 fi 435 436 if [ "${JIT_REQ}" = "yes" -a "${JIT_VER:-0}" -lt "${JIT_MAX}" ]; then 437 return 1 438 fi 439 440 if [ "${SHORTEST}" = "yes" ]; then 441 return 1 442 fi 443 444 return 0 445} 446 447 448# 449# luapc 450# 451# wrapper around `pkg-config ... LIB`, where LIB is derived by 452# searching for all libraries with "lua" in the name that have a 453# --modversion equal to the release version printed by ${LUA_PATH} -v. 454# 455LUAPC_LIB= 456 457luapc() { 458 [ -n "${LUA_PATH}" ] || return 0 459 460 [ -n "${PKGCONFIG}" ] || return 0 461 462 # find pkg-config library name 463 if [ -z "${LUAPC_LIB}" ]; then 464 V="$("${LUA_PATH}" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^Lua[^ ]* \([0123456789][0123456789]*\(\.[0123456789][0123456789]*\)*\).*/\1/p')" 465 466 [ -n "${V}" ] || return 0 467 468 V_N=$(mmp2num "${V}") 469 470 for LIB in $("${PKGCONFIG}" --list-all </dev/null 2>>/dev/null | sed -ne 's/^\(lua[^ ]*\).*/\1/p'); do 471 M="$("${PKGCONFIG}" --modversion ${LIB} || true)" 472 473 # break immediately on exact match 474 if [ "${V}" = "${M}" ]; then 475 LUAPC_LIB="${LIB}" 476 477 break 478 fi 479 480 # 481 # NOTE: On Ubuntu 14.04 pkg-config --modversion 482 # lua5.2 prints 5.2.0 even though the release 483 # version is 5.2.3 (what lua5.2 -v prints). 484 # 485 # If the major.minor components match, then 486 # tentatively use that package name. 487 # 488 M_N=$(mmp2num "${M}" 0 0 0) 489 490 if [ "$((${V_N} / 100))" -eq "$((${M_N} / 100))" ]; then 491 LUAPC_LIB="${LIB}" 492 fi 493 done 494 495 [ -n "${LUAPC_LIB}" ] || return 0 496 fi 497 498 ${PKGCONFIG} "$@" "${LUAPC_LIB}" </dev/null 2>>/dev/null || true 499} 500 501 502# 503# findinstalldir package.path|package.cpath [preferred-path ...] 504# 505findinstalldir() { 506 V_DIR=$((${LUA_VER} / 100 % 100)).$((${LUA_VER} % 100)) 507 508 if [ "${1}" = "package.cpath" -o "${1}" = "cdir" ]; then 509 ARRAY="package.cpath" 510 511 DIR="$(luapc --variable INSTALL_CMOD)" 512 [ -n "${DIR}" ] && set -- "$@" "${DIR}" 513 514 DIR="$(luapc --variable INSTALL_LIB)" 515 [ -n "${DIR}" ] && set -- "$@" "${DIR}/lua/${V_DIR}" 516 517 DIR="$(luapc --variable libdir)" 518 [ -n "${DIR}" ] && set -- "$@" "${DIR}/lua/${V_DIR}" 519 520 DIR="$(luapc --variable prefix)" 521 [ -n "${DIR}" ] && set -- "$@" "${DIR}/lib/lua/${V_DIR}" 522 523 # LuaJIT installations tend to include 524 # /usr/local/lib/lua/5.1 as one of the first paths, ordered 525 # before the LuaJIT installation prefix, and regardless of 526 # whether there exists a /usr/local/lib/lua/5.1. 527 set -- "$@" "${LUA_PATH}/../../lib/lua/${V_DIR}" 528 set -- "$@" "${LUA_PATH}/../../lib/*/lua/${V_DIR}" # e.g. lib/x86_64-linux-gnu 529 else 530 ARRAY="package.path" 531 532 DIR="$(luapc --variable INSTALL_LMOD)" 533 [ -n "${DIR}" ] && set -- "$@" "${DIR}" 534 535 DIR="$(luapc --variable prefix)" 536 [ -n "${DIR}" ] && set -- "$@" "${DIR}/share/lua/${V_DIR}" 537 538 # See above LuaJIT note. Although the built-in package.path 539 # usually orders the LuaJIT installation prefix first. 540 set -- "$@" "${LUA_PATH}/../../share/lua/${V_DIR}" 541 fi 542 543 shift 544 545 if [ $# -eq 0 ]; then 546 set -- "/nonexistent" # cannot expand empty $@ on some implementations 547 fi 548 549 "${LUA_PATH}" - "$@" <<-EOF 550 -- 551 -- actual pkg-config variable on Ubuntu 14.04 552 -- 553 -- /usr//share/lua/5.1 554 -- 555 local function fixpath(path) 556 local stack = { path:match"^/" and "" or "." } 557 558 for ent in path:gmatch"([^/]+)" do 559 if ent == ".." and #stack > 1 then 560 stack[#stack] = nil 561 elseif ent ~= "." then 562 stack[#stack + 1] = ent 563 end 564 end 565 566 return table.concat(stack, "/") 567 end 568 569 local function topattern(path) 570 if string.match(path, "*") then 571 path = string.gsub(path, "%%", "%%") 572 return string.gsub(path, "*", "[^/]+") 573 end 574 end 575 576 local dirs = { } 577 578 for dir in ${ARRAY}:gmatch"([^;?]+)/" do 579 dir = fixpath(dir) 580 581 if dir ~= "." then 582 dirs[#dirs + 1] = dir 583 end 584 end 585 586 for _, arg in ipairs{ ... } do 587 arg = fixpath(arg) 588 589 local pat = topattern(arg) 590 591 for _, dir in ipairs(dirs) do 592 if arg == dir then 593 print(dir) 594 os.exit(0) 595 elseif pat and string.match(dir, pat) then 596 print(dir) 597 os.exit(0) 598 end 599 end 600 end 601 602 if dirs[1] then 603 print(dirs[1]) 604 os.exit(0) 605 else 606 os.exit(1) 607 end 608 EOF 609} 610 611 612# 613# findversion 614# 615findversion() { 616 tryluainclude "lua.h" 617 618 if foundversion; then 619 return 0 620 fi 621 622 623 # iterate through CPPFLAGS to probe different precedence 624 if [ "${API_VER:-0}" -lt "${API_MAX}" ]; then 625 IFS=: 626 set -- ${CPPDIRS} 627 unset IFS 628 629 if [ $# -gt 0 ]; then 630 for D; do 631 tryluainclude "${D}/lua.h" 632 633 if foundversion; then 634 return 0 635 fi 636 done 637 fi 638 fi 639 640 641 if [ -n "${PKGCONFIG}" ]; then 642 PKGFLAGS="$("${PKGCONFIG}" --list-all </dev/null 2>>/dev/null | sed -ne 's/^\(lua[^ ]*\).*/\1/p' | xargs -- ${PKGCONFIG} --cflags 2>>/dev/null | cat)" 643 PKGDIRS="$(idirs "${PKGFLAGS}")" 644 645 IFS=: 646 set -- ${PKGDIRS} 647 unset IFS 648 649 if [ $# -gt 0 ]; then 650 for D; do 651 tryluainclude "${D}/lua.h" 652 653 if foundversion; then 654 return 0 655 fi 656 done 657 fi 658 fi 659 660 661 IFS=: 662 set -- ${INCDIRS} 663 unset IFS 664 665 if [ $# -gt 0 ]; then 666 for D; do 667 tryluainclude "${D}/lua.h" 668 669 if foundversion; then 670 return 0 671 fi 672 done 673 fi 674 675 676 if [ "${RECURSE}" != "yes" ]; then 677 [ "${API_VER:-0}" -gt 0 ] 678 return $? 679 fi 680 681 682 # recurse into CPPDIRS 683 IFS=: 684 set -- ${CPPDIRS} 685 unset IFS 686 687 if [ $# -gt 0 ]; then 688 for D; do 689 glob "${D}/lua.h" "${MAXDEPTH}" tryluainclude || : 690 691 if foundversion; then 692 return 0 693 fi 694 done 695 fi 696 697 698 # recurse into INCDIRS 699 IFS=: 700 set -- ${INCDIRS} 701 unset IFS 702 703 if [ $# -gt 0 ]; then 704 for D; do 705 glob "${D}/lua.h" "${MAXDEPTH}" tryluainclude || : 706 707 if foundversion; then 708 return 0 709 fi 710 done 711 fi 712 713 714 # if we can find the lua interpreter, use it as a reference for 715 # header locations. 716 if findlua; then 717 D="${LUA_PATH%/*}" 718 D="${D%/*}/include" 719 720 if [ -d "${D}" ]; then 721 glob "${D}/lua.h" "${MAXDEPTH}" tryluainclude || : 722 723 if foundversion; then 724 return 0 725 fi 726 fi 727 fi 728 729 [ "${API_VER:-0}" -gt 0 ] 730} 731 732 733# 734# Unlike API version checking, this is less likely to be accurately forward 735# compatible. 736# 737trylib() { 738 testsym "${1}" "lua_newstate" || return 1 739 740 # exclude C++ 741 [ "${1#*++}" = "${1}" ] || return 1 742 743 V=0 744 J=0 745 D= 746 F="${1##*/}" 747 L= 748 749 if [ "${1%/*}" != "${1}" ]; then 750 D="${1%/*}" 751 752 # cleanup after Solaris directory prune trick 753 if [ "${D##*/./}" != "${D}" ]; then 754 D="${D%%/./*}/${D##*/./}" 755 else 756 D="${D%/.}" 757 fi 758 fi 759 760 L="${F#lib}" 761 L="${L%.so}" 762 L="${L%.a}" 763 L="${L%.dylib}" 764 765 766 # FIXME: need more versioning tests 767 if testsym "${1}" "lua_getfenv"; then 768 V=501 769 elif testsym "${1}" "lua_yieldk"; then 770 if testsym "${1}" "lua_getctx"; then 771 V=502 772 else 773 V=503 774 fi 775 else 776 return 1 777 fi 778 779 [ "$V" -gt 0 -a "$V" -ge "${LIBLUA_VER:-0}" ] || return 1 780 781 [ "$V" -gt "${LIBLUA_VER:-0}" -o "${#D}" -lt "${#LIBLUA_DIR}" -o \( "${JIT_REQ}" = "yes" -a "${LIBJIT_VER:-0}" -lt "${JIT_MAX}" \) ] || return 1 782 783 [ "$V" -ge "${API_MIN}" -a "$V" -le "${API_MAX}" ] || return 1 784 785 786 if [ -n "${JIT_REQ}" ]; then 787 # FIXME: need more versioning tests 788 if testsym "${1}" "luaopen_jit"; then 789 J=20000 790 fi 791 792 if [ "${JIT_REQ}" = "skip" ]; then 793 [ "${J}" -eq 0 ] || return 1 794 elif [ "${JIT_REQ}" = "yes" ]; then 795 [ "$J" -ge "${LIBJIT_VER:-0}" ] || return 1 796 [ "$J" -gt "${LIBJIT_VER:-0}" -o "${#D}" -lt "${#LIBJIT_DIR}" ] || return 1 797 [ "$J" -ge ${JIT_MIN} ] || return 1 798 [ "$J" -le "${JIT_MAX}" ] || return 1 799 800 LIBJIT_VER="$J" 801 LIBJIT_DIR="$D" 802 LIBJIT_LIB="$L" 803 fi 804 fi 805 806 LIBLUA_VER="$V" 807 LIBLUA_DIR="$D" 808 LIBLUA_LIB="$L" 809} 810 811 812# 813# foundlib 814# 815# true if found the best (maximum) possible version, false otherwise 816# 817foundlib() { 818 if [ "${LIBLUA_VER:-0}" -lt "${API_MAX}" ]; then 819 return 1 820 fi 821 822 if [ "${JIT_REQ}" = "yes" -a "${LIBJIT_VER:-0}" -lt "${JIT_MAX}" ]; then 823 return 1 824 fi 825 826 if [ "${SHORTEST}" = "yes" ]; then 827 return 1 828 fi 829 830 return 0 831} 832 833 834findlib() { 835 if [ -n "${PKGCONFIG}" ]; then 836 PKGFLAGS="$("${PKGCONFIG}" --list-all </dev/null 2>>/dev/null | sed -ne 's/^\(lua[^ ]*\).*/\1/p' | xargs -- ${PKGCONFIG} --libs 2>>/dev/null | cat)" 837 PKGDIRS="$(ldirs "${PKGFLAGS}")" 838 PKGDIRS="${PKGDIRS}${PKGDIRS:+:}/lib:/usr/lib:/usr/local/lib" 839 NUMDIRS="$(count "${PKGDIRS}")" 840 PKGLIBS="$(xdirs "l" "${PKGFLAGS}")" 841 NUMLIBS="$(count "${PKGLIBS}")" 842 ALLDIRS="${PKGDIRS}${PKGLIBS:+:}${PKGLIBS}" 843 844 IFS=: 845 set -- ${ALLDIRS} 846 unset IFS 847 848 I=1 849 while [ $I -le ${NUMDIRS} ]; do 850 K=$((1 + ${NUMDIRS})) 851 while [ $K -le $# ]; do 852 findlib_L=$(eval "printf \${$I}") 853 findlib_l=$(eval "printf \${$K}") 854 855 #printf -- "I=$I K=$K $findlib_L/lib$findlib_l*.*\n" 856 857 glob "${findlib_L}/lib${findlib_l}*.*" 0 trylib || : 858 859 if foundlib; then 860 return 0; 861 fi 862 863 glob "${findlib_L}/lib${findlib_l}*.*" ${MAXDEPTH} trylib || : 864 865 if foundlib; then 866 return 0; 867 fi 868 869 K=$(($K + 1)) 870 done 871 I=$(($I + 1)) 872 done 873 fi 874 875 ALLDIRS="${LDDIRS}${LDDIRS:+:}${LIBDIRS}" 876 877 IFS=: 878 set -- ${ALLDIRS} 879 unset IFS 880 881 for findlib_D; do 882 glob "${findlib_D}/liblua*.*" "${MAXDEPTH}" trylib || : 883 884 if foundlib; then 885 return 0 886 fi 887 done 888 889 # if we can find the lua interpreter, use it as a reference for 890 # library locations. 891 if findlua; then 892 findlib_D="${LUA_PATH%/*}" 893 findlib_D="${findlib_D%/*}/lib" 894 895 if [ -d "${findlib_D}" ]; then 896 glob "${findlib_D}/liblua*.*" "${MAXDEPTH}" trylib || : 897 898 if foundlib; then 899 return 0 900 fi 901 fi 902 fi 903} 904 905 906# check setuid and setgid mode 907safeperm() { 908 [ -f "$1" -a ! -u "$1" -a ! -g "$1" ] 909} 910 911 912tryluac() { 913 tryluac_F="${1}" 914 915 [ -x "${tryluac_F}" ] && safeperm "${tryluac_F}" || return 0 916 917 tryluac_V="$("${tryluac_F}" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^Lua \([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" 918 : ${tryluac_V:=0} 919 tryluac_V="$((${tryluac_V%%.*} * 100 + ${tryluac_V##*.} % 100))" 920 921 [ "${tryluac_V}" -gt 0 -a "${tryluac_V}" -ge "${LUAC_VER:-0}" ] || return 0 922 923 [ "${tryluac_V}" -gt "${LUAC_VER:-0}" -o "${#tryluac_F}" -lt "${#LUAC_PATH}" ] || return 0 924 925 [ "${tryluac_V}" -ge "${API_MIN}" -a "${tryluac_V}" -le "${API_MAX}" ] || return 0 926 927 printf "return true" 2>>/dev/null | ${tryluac_F} -p - </dev/null >>/dev/null 2>&1 || return 0 928 929 LUAC_PATH="${tryluac_F}" 930 LUAC_VER="${tryluac_V}" 931} 932 933# 934# foundluac 935# 936# true if found the best (maximum) possible version, false otherwise 937# 938foundluac() { 939 if [ "${LUAC_VER:-0}" -lt "${API_MAX}" ]; then 940 return 1 941 fi 942 943 if [ "${SHORTEST}" = "yes" ]; then 944 return 1 945 fi 946 947 return 0 948} 949 950findluac() { 951 if [ $# -eq 0 ]; then 952 IFS=: 953 set -- ${GLOB:-${GLOB_LUAC}} 954 unset IFS 955 fi 956 957 for findluac_G; do 958 IFS=: 959 for findluac_D in ${PATH}; do 960 unset IFS 961 962 glob "${findluac_D}/${findluac_G}" 0 tryluac || : 963 964 if foundluac; then 965 return 0 966 fi 967 done 968 969 IFS=: 970 for findluac_D in ${BINDIRS}; do 971 unset IFS 972 973 glob "${findluac_D}/${findluac_G}" "${MAXDEPTH}" tryluac || : 974 975 if foundluac; then 976 return 0 977 fi 978 done 979 980 unset IFS 981 done 982 983 [ "${LUAC_VER:-0}" -gt 0 ] && [ "${#LUAC_PATH}" -gt 0 ] 984} 985 986 987isinteger() { 988 I="${1}" 989 990 [ "${#I}" -gt 0 ] || return 1 991 992 while [ "${#I}" -gt 0 ]; do 993 if [ "${I##[0123456789]}" = "${I}" ]; then 994 return 1 995 fi 996 997 I=${I##[0123456789]} 998 done 999 1000 return 0 1001} 1002 1003 1004checkints() { 1005 while [ $# -gt 0 ]; do 1006 if ! isinteger "${1}"; then 1007 warn "%s: not a number" "${1}" 1008 return 1 1009 fi 1010 1011 shift 1012 done 1013} 1014 1015 1016# Only major.minor for matching LUA_VERSION_NUM in lua.h. Also, _VERSION 1017# only includes major.minor. 1018lua2num() { 1019 M=0 1020 m="${2:-0}" 1021 1022 IFS=. 1023 set -- ${1} 1024 unset IFS 1025 1026 M=${1:-${M}} 1027 m=${2:-${m}} 1028 1029 checkints $M $m 1030 1031 printf "$((${M} * 100 + ${m}))\n" 1032} 1033 1034 1035# All major.minor.patch for matching LUAJIT_VERSION_NUM in luajit.h. 1036jit2num() { 1037 M=0 1038 m="${2:-0}" 1039 p="${3:-0}" 1040 1041 IFS=. 1042 set -- ${1} 1043 unset IFS 1044 1045 M=${1:-${M}} 1046 m=${2:-${m}} 1047 p=${3:-${p}} 1048 1049 checkints $M $m $p 1050 1051 printf "$((${M} * 10000 + ${m} * 100 + ${p}))\n" 1052} 1053 1054 1055mmp2num() { 1056 M="${2:-0}" 1057 m="${3:-0}" 1058 p="${4:-0}" 1059 1060 IFS=".+-_" 1061 set -- ${1} 1062 unset IFS 1063 1064 if isinteger "${1:-}"; then 1065 M=${1} 1066 fi 1067 1068 if isinteger "${2:-}"; then 1069 m=${2} 1070 fi 1071 1072 if isinteger "${3:-}"; then 1073 p=${3} 1074 fi 1075 1076 checkints $M $m $p 1077 1078 printf "$((${M} * 10000 + ${m} * 100 + ${p}))\n" 1079} 1080 1081 1082trylua() { 1083 trylua_F="${1}" 1084 [ -x "${trylua_F}" ] && safeperm "${trylua_F}" || return 0 1085 1086 trylua_V="$("${trylua_F}" -e 'print(string.match(_VERSION, [[[%d.]+]]))' </dev/null 2>>/dev/null | head -n1 | sed -ne 's/^\([0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" 1087 : ${trylua_V:=0} 1088 trylua_V="$((${trylua_V%%.*} * 100 + ${trylua_V##*.} % 100))" 1089 1090 [ "${trylua_V}" -gt 0 -a "${trylua_V}" -ge "${LUA_VER:-0}" ] || return 0 1091 1092 [ "${trylua_V}" -gt "${LUA_VER:-0}" -o "${#trylua_F}" -lt "${#LUA_PATH}" ] || return 0 1093 1094 [ "${trylua_V}" -ge "${API_MIN}" -a "${trylua_V}" -le "${API_MAX}" ] || return 0 1095 1096 if [ -n "${JIT_REQ}" ]; then 1097 J="$("${trylua_F}" -v </dev/null 2>&1 | head -n1 | sed -ne 's/^LuaJIT \([0123456789][0123456789]*\.[0123456789][0123456789]*\.[0123456789][0123456789]*\).*/\1/p')" 1098 J="$(jit2num ${J:-0})" 1099 1100 if [ "${JIT_REQ}" = "skip" ]; then 1101 [ "${J}" -eq 0 ] || return 0 1102 elif [ "${JIT_REQ}" = "yes" ]; then 1103 [ "${J}" -gt 0 ] || return 0 1104 [ "${J}" -ge "${JIT_MIN}" ] || return 0 1105 [ "${J}" -le "${JIT_MAX}" ] || return 0 1106 fi 1107 fi 1108 1109 LUA_PATH="${trylua_F}" 1110 LUA_VER="${trylua_V}" 1111} 1112 1113# 1114# foundlua 1115# 1116# true if found the best (maximum) possible version, false otherwise 1117# 1118foundlua() { 1119 if [ "${LUA_VER:-0}" -lt "${API_MAX}" ]; then 1120 return 1 1121 fi 1122 1123 if [ "${SHORTEST}" = "yes" ]; then 1124 return 1 1125 fi 1126 1127 return 0 1128} 1129 1130findlua() { 1131 if [ $# -eq 0 ]; then 1132 IFS=: 1133 set -- ${GLOB:-${GLOB_LUA}} 1134 unset IFS 1135 fi 1136 1137 for findlua_G; do 1138 IFS=: 1139 for findlua_D in ${PATH}; do 1140 unset IFS 1141 1142 glob "${findlua_D}/${findlua_G}" 0 trylua || : 1143 1144 if foundlua; then 1145 return 0 1146 fi 1147 done 1148 1149 IFS=: 1150 for findlua_D in ${BINDIRS}; do 1151 unset IFS 1152 1153 glob "${findlua_D}/${findlua_G}" "${MAXDEPTH}" trylua || : 1154 1155 if foundlua; then 1156 return 0 1157 fi 1158 done 1159 1160 unset IFS 1161 done 1162 1163 [ "${LUA_VER:-0}" -gt 0 ] && [ "${#LUA_PATH}" -gt 0 ] 1164} 1165 1166 1167ccname() { 1168 runcc -E - <<-EOF | awk '/sunpro/||/clang/||/gcc/||/other/{ print $1; exit; }' 1169 #if defined __SUNPRO_C 1170 sunpro 1171 #elif defined __clang__ 1172 clang 1173 #elif defined __GNUC__ 1174 gcc 1175 #else 1176 other 1177 #endif 1178 EOF 1179} 1180 1181 1182usage() { 1183 cat <<-EOF 1184 usage: ${0##*/} [-I:L:P:d:De:krm:xsv:j:JVh] cppflags|version|lua|luac|... 1185 -I PATH additional search directory for includes 1186 -L PATH additional search directory for libraries 1187 -P PATH additional search directory for binaries 1188 -d PATH use PATH as sandbox directory; a random 16 byte suffix is 1189 generated from /dev/urandom and the directory removed on exit 1190 unless a trailing "/" is present 1191 (default sandbox is \$TMPDIR/${0##*/}-XXXXXXXXXXXXXXXX) 1192 -D do not create a sandbox 1193 -e GLOB glob pattern for finding utilities (lua, luac, etc) 1194 -k query pkg-config if available 1195 -r recursively search directories 1196 -m MAXDEPTH limit recursion to MAXDEPTH 1197 -s find shortest pathname, otherwise print first best match 1198 -v VERSION require specific Lua version or range 1199 (e.g. "5.1" or "5.1-5.2") 1200 -j VERSION require specific LuaJIT version or range 1201 (e.g. "2.0.1"; empty ranges like "-" force any LuaJIT version) 1202 -J skip LuaJIT if encountered 1203 -V print this script's version information 1204 -h print this usage message 1205 1206 cppflags print derived additional CPPFLAGS necessary 1207 version print derived Lua API version from cppflags discovery 1208 ldflags print derived additional LDFLAGS necessary (TODO) 1209 libs print derived additional LIBS necessary (TODO) 1210 libversion print derived Lua API version from ldflags/libs discovery 1211 luac print path to luac utility ($(printf "${GLOB_LUA}" | tr ':' ' ')) 1212 lua print path to lua interpreter ($(printf "${GLOB_LUAC}" | tr ':' ' ')) 1213 package.path print preferred module install path 1214 package.cpath print preferred C module install path 1215 ccname print CC name (e.g. sunpro, clang, gcc) 1216 evalmacro run internal macro evaluator for debugging 1217 testsym run internal library symbol reader for debugging 1218 1219 This utility is used to derive compiler flags and filesystem paths 1220 necessary to utilize Lua, LuaJIT, and particular versions thereof. 1221 On success it prints the requested information and exits with 0, 1222 otherwise it fails with an exit status of 1. 1223 1224 Note that cppflags may not print anything if no additional flags are 1225 required to compile against the requested API version. 1226 1227 When searching, the highest Lua version is preferred. Searching 1228 stops once the highest version in the allowable range is found 1229 unless the -s flag is specified. 1230 1231 LuaJIT is treated like any other Lua installation. If an explicit 1232 LuaJIT version or range is specified, then only LuaJIT installations 1233 will match. To exclude LuaJIT entirely use the -J switch. 1234 1235 This utility processes the environment variables CC, CPPFLAGS, 1236 LDFLAGS, and PATH if present. If recursion is requested, then 1237 directories specified in CPPFLAGS, LDFLAGS, and PATH are also 1238 recursed. 1239 1240 If the environment variable CPPFLAGS is empty and no -I options are 1241 specified directly, then /usr/include and /usr/local/include are 1242 used when probing for cppflags and API version. 1243 1244 Report bugs to <william@25thandClement.com> 1245 EOF 1246} 1247 1248 1249version() { 1250 cat <<-EOF 1251 luapath $MYVERSION 1252 vendor $MYVENDOR 1253 release $MYVERSION 1254 EOF 1255} 1256 1257 1258while getopts I:L:P:d:De:krm:xsv:j:JVh OPT; do 1259 case "${OPT}" in 1260 I) 1261 INCDIRS="${INCDIRS:-}${INCDIRS:+:}${OPTARG}" 1262 ;; 1263 L) 1264 LIBDIRS="${LIBDIRS:-}${LIBDIRS:+:}${OPTARG}" 1265 ;; 1266 P) 1267 BINDIRS="${BINDIRS:-}${BINDIRS:+:}${OPTARG}" 1268 ;; 1269 d) 1270 SANDBOX="${OPTARG}" 1271 ;; 1272 D) 1273 SANDBOX= 1274 ;; 1275 e) 1276 GLOB="${GLOB:-}${GLOB:+:}${OPTARG}" 1277 ;; 1278 k) 1279 PKGCONFIG="$(command -v pkg-config || true)" 1280 ;; 1281 r) 1282 RECURSE=yes 1283 ;; 1284 m) 1285 if [ "${#OPTARG}" -eq 0 -o -n "${OPTARG##[0123456789]}" ]; then 1286 panic "%s: invalid maxdepth" "${OPTARG}" 1287 fi 1288 1289 MAXDEPTH="${OPTARG}" 1290 ;; 1291 x) 1292 # 1293 # NOTE: This option was 1294 # 1295 # -x do not cross device mounts when recursing 1296 # 1297 # but is currently unsupported as our built-in glob function 1298 # does not implement this functionality. Previously this 1299 # option caused -xdev to be added to invocations of find(1). 1300 ;; 1301 s) 1302 SHORTEST=yes 1303 ;; 1304 v) 1305 MIN=${OPTARG%%[,:-]*} 1306 MAX=${OPTARG##*[,:-]} 1307 1308 API_MIN="$(lua2num ${MIN:-0} 0)" 1309 API_MAX="$(lua2num ${MAX:-99} 99)" 1310 1311 if [ "${API_MIN}" -gt "${API_MAX}" ]; then 1312 panic "%s: invalid version range" "${OPTARG}" 1313 fi 1314 1315 ;; 1316 j) 1317 MIN=${OPTARG%%[,:-]*} 1318 MAX=${OPTARG##*[,:-]} 1319 1320 JIT_MIN="$(jit2num ${MIN:-0} 0 0)" 1321 JIT_MAX="$(jit2num ${MAX:-99} 99 99)" 1322 1323 if [ "${JIT_MIN}" -gt "${JIT_MAX}" ]; then 1324 panic "%s: invalid version range" "${OPTARG}" 1325 fi 1326 1327 JIT_REQ=yes 1328 ;; 1329 J) 1330 JIT_REQ=skip 1331 ;; 1332 V) 1333 version 1334 exit 0 1335 ;; 1336 h) 1337 usage 1338 exit 0 1339 ;; 1340 *) 1341 usage >&2 1342 exit 1 1343 ;; 1344 esac 1345done 1346 1347shift $(($OPTIND - 1)) 1348 1349 1350[ "${RECURSE}" = "yes" ] || MAXDEPTH=0 1351 1352 1353for U in "${CC}" grep od rm rmdir sed xargs; do 1354 ! command -v "${U}" >>/dev/null 2>&1 || continue 1355 1356 # ${CC} might have trailing flags or invoke the compiler through env 1357 ! command -v "${U%% *}" >>/dev/null 2>&1 || continue 1358 1359 warn "%s: command not found" "${U}" 1360done 1361 1362 1363if [ -n "${SANDBOX}" ]; then 1364 if [ "${SANDBOX}" = "${SANDBOX%/}" ]; then 1365 if [ ! -c "${DEVRANDOM}" ]; then 1366 # TODO: expand DEVRANDOM into set of different possibilities to check 1367 panic "%s: no character random device available" "${DEVRANDOM}" 1368 fi 1369 1370 TMP="${SANDBOX}$(od -An -N8 -tx1 < ${DEVRANDOM} 2>>/dev/null | tr -d ' ')" 1371 1372 if [ ${#TMP} -ne $((${#SANDBOX} + 16)) ]; then 1373 panic "%s: unable to generate random suffix" "${SANDBOX}" 1374 fi 1375 1376 SANDBOX="${TMP}" 1377 1378 trap "cd .. && rm -f -- ${SANDBOX}/* && rmdir -- ${SANDBOX}" EXIT 1379 fi 1380 1381 if [ ! -d "${SANDBOX}" ]; then 1382 OMASK="$(umask)" 1383 umask 0777 1384 mkdir -m0550 -- "${SANDBOX}" || exit 1 1385 umask ${OMASK} 1386 fi 1387 1388 cd ${SANDBOX} 1389fi 1390 1391 1392CPPDIRS="$(idirs "${CPPFLAGS:-}")" 1393 1394if [ -z "${CPPDIRS}" -a -z "${INCDIRS}" ]; then 1395 INCDIRS="/usr/include:/usr/local/include" 1396fi 1397 1398 1399LDDIRS="$(ldirs "${LDFLAGS:-}")" 1400 1401if [ -z "${LDDIRS}" -a -z "${LIBDIRS}" ]; then 1402 LIBDIRS="/lib:/usr/lib:/usr/local/lib" 1403fi 1404 1405 1406case "${1:-}" in 1407cppflags) 1408 findversion || exit 1 1409 1410 [ "${API_VER:-0}" -gt 0 ] || exit 1 1411 1412 [ -z "${API_DIR:-}" ] || printf -- "-I${API_DIR}\n" 1413 1414 ;; 1415version) 1416 findversion || exit 1 1417 1418 printf "$(((${API_VER} / 100) % 100)).$((($API_VER) % 100))\n" 1419 1420 ;; 1421ldflags) 1422 findlib 1423 1424 [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1 1425 1426 if [ "${#LIBLUA_DIR}" -gt 0 ]; then 1427 printf -- "-L%s\n" "${LIBLUA_DIR}" 1428 fi 1429 1430 ;; 1431libs) 1432 findlib 1433 1434 [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1 1435 1436 printf -- "-l%s\n" "${LIBLUA_LIB}" 1437 1438 ;; 1439libv*) 1440 findlib 1441 1442 [ "${LIBLUA_VER:-0}" -gt 0 ] || exit 1 1443 1444 printf "$(((${LIBLUA_VER} / 100) % 100)).$((($LIBLUA_VER) % 100))\n" 1445 1446 ;; 1447luac) 1448 shift 1449 1450 if [ $# -gt 0 ]; then 1451 append GLOB $* 1452 fi 1453 1454 findluac || exit 1 1455 1456 printf -- "${LUAC_PATH}\n" 1457 1458 ;; 1459lua) 1460 shift 1461 1462 if [ $# -gt 0 ]; then 1463 append GLOB $* 1464 fi 1465 1466 findlua || exit 1 1467 1468 printf -- "${LUA_PATH}\n" 1469 1470 ;; 1471ldir|cdir) 1472 # 1473 # ldir and cdir were deprecated on 2014-12-18. On 2016-03-25 they 1474 # were revived because their names are more intuitive than 1475 # package.path and package.cpath. For now try to support the 1476 # semantics of both by assuming interpreter glob patterns only match 1477 # file names, while preferred install directory string.match 1478 # expressions have directory components. 1479 # 1480 if true; then 1481 MODE="${1}" 1482 1483 # move command to end; rotates to ${1} after loop 1484 set -- "$@" "${1}" 1485 shift 1486 1487 cdir_I=0 1488 cdir_N="$(($# - 1))" 1489 while [ "${cdir_I}" -lt "${cdir_N}" ]; do 1490 if [ "${1#*/}" = "${1}" ]; then 1491 append GLOB "${1}" 1492 warn "%s: passing glob patterns to %s is deprecated" "${1}" "${MODE}" 1493 else 1494 set -- "$@" "${1}" 1495 fi 1496 shift 1497 cdir_I=$((${cdir_I} + 1)) 1498 done 1499 fi 1500 1501 findlua || exit 1 1502 1503 findinstalldir "$@" || exit 1 1504 1505 ;; 1506package.path|package.cpath) 1507 findlua || exit 1 1508 1509 findinstalldir "$@" || exit 1 1510 1511 ;; 1512ccname) 1513 ccname 1514 1515 ;; 1516evalmacro) 1517 shift 1518 1519 evalmacro $* 1520 ;; 1521testsym) 1522 shift 1523 1524 if testsym $*; then 1525 printf "found\n" 1526 exit 0 1527 else 1528 printf "not found\n" 1529 exit 1 1530 fi 1531 ;; 1532*) 1533 if [ -n "${1:-}" ]; then 1534 warn "%s: unknown command" "${1}" 1535 else 1536 warn "no command specified" 1537 fi 1538 1539 exit 1 1540 ;; 1541esac 1542 1543exit 0 1544